125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print information from ELF file in human-readable form.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 1999-2012 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This file is part of Red Hat elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <argp.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ctype.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <dwarf.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <langinfo.h>
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libdw.h>
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libdwfl.h>
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h>
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <locale.h>
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdarg.h>
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <time.h>
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h>
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/libelfP.h"
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/common.h"
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libebl/libeblP.h"
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdw/libdwP.h"
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdwfl/libdwflP.h"
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdw/memory-access.h"
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Name and version of program.  */
6425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_version (FILE *stream, struct argp_state *state);
6525b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Bug report address.  */
6825b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Definitions of arguments for argp functions.  */
7125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct argp_option options[] =
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "all", 'a', NULL, 0,
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "histogram", 'I', NULL, 0,
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display histogram of bucket list lengths"), 0 },
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "arch-specific", 'A', NULL, 0,
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display architecture specific information, if any"), 0 },
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "exception", 'e', NULL, 0,
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display sections for exception handling"), 0 },
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display DWARF section content.  SECTION can be one of abbrev, "
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng       "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, "
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng       "macinfo, or exception"), 0 },
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "hex-dump", 'x', "SECTION", 0,
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Print string contents of sections"), 0 },
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "archive-index", 'c', NULL, 0,
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display the symbol index of an archive"), 0 },
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Output control:"), 0 },
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "numeric-addresses", 'N', NULL, 0,
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Do not find symbol names for addresses in DWARF data"), 0 },
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "wide", 'W', NULL, 0,
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Ignored for compatibility (lines always wide)"), 0 },
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, NULL, 0 }
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Short description of program.  */
11525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char doc[] = N_("\
11625b3c049e70834cf33790a28643ab058b507b35cBen ChengPrint information from ELF file in human-readable form.");
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Strings for arguments in help texts.  */
11925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char args_doc[] = N_("FILE...");
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototype for option handler.  */
12225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Data structure to communicate with argp functions.  */
12525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp argp =
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  options, parse_opt, args_doc, doc, NULL, NULL, NULL
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Flags set by the option controlling the output.  */
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if dynamic segment should be printed.  */
13425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_dynamic_table;
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the file header should be printed.  */
13725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_file_header;
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the program headers should be printed.  */
14025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_program_header;
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if relocations should be printed.  */
14325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_relocations;
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the section headers should be printed.  */
14625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_section_header;
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the symbol table should be printed.  */
14925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_symbol_table;
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the version information should be printed.  */
15225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_version_info;
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if section groups should be printed.  */
15525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_section_groups;
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if bucket list length histogram should be printed.  */
15825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_histogram;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the architecture specific data should be printed.  */
16125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_arch;
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if note section content should be printed.  */
16425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_notes;
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if SHF_STRINGS section content should be printed.  */
16725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_string_sections;
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if archive index should be printed.  */
17025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_archive_index;
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if any of the control options except print_archive_index is set.  */
17325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool any_control_option;
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if we should print addresses from DWARF in symbolic form.  */
17625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_address_names = true;
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Select printing of debugging sections.  */
17925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum section_e
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_abbrev = 1,		/* .debug_abbrev  */
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_aranges = 2,		/* .debug_aranges  */
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_frame = 4,		/* .debug_frame or .eh_frame & al.  */
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_info = 8,		/* .debug_info, .debug_types  */
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_types = section_info,
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_line = 16,		/* .debug_line  */
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_loc = 32,		/* .debug_loc  */
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_pubnames = 64,	/* .debug_pubnames  */
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_str = 128,		/* .debug_str  */
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_macinfo = 256,	/* .debug_macinfo  */
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_ranges = 512, 	/* .debug_ranges  */
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_exception = 1024,	/* .eh_frame & al.  */
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_gdb_index = 2048,	/* .gdb_index  */
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_all = (section_abbrev | section_aranges | section_frame
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 | section_info | section_line | section_loc
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 | section_pubnames | section_str | section_macinfo
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 | section_ranges | section_exception | section_gdb_index)
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} print_debug_sections, implicit_debug_sections;
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Select hex dumping of sections.  */
20125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument *dump_data_sections;
20225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument **dump_data_sections_tail = &dump_data_sections;
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Select string dumping of sections.  */
20525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument *string_sections;
20625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument **string_sections_tail = &string_sections;
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20825b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct section_argument
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct section_argument *next;
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *arg;
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool implicit;
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Numbers of sections and program headers in the file.  */
21625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t shnum;
21725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t phnum;
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Declarations of local functions.  */
22125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void process_file (int fd, const char *fname, bool only_one);
22225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void process_elf_file (Dwfl_Module *dwflmod, int fd);
22325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
22425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
22525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
22625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_scngrp (Ebl *ebl);
22725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_dynamic (Ebl *ebl);
22825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
22925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       GElf_Shdr *shdr);
23125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				GElf_Shdr *shdr);
23325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_symtab (Ebl *ebl, int type);
23425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
23525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_verinfo (Ebl *ebl);
23625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
23725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
23825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_versym (Ebl *ebl, Elf_Scn *scn,
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   GElf_Shdr *shdr);
24025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
24125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_hash (Ebl *ebl);
24225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
24325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_liblist (Ebl *ebl);
24425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
24525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void dump_data (Ebl *ebl);
24625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void dump_strings (Ebl *ebl);
24725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_strings (Ebl *ebl);
24825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void dump_archive_index (Elf *, const char *);
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25125b3c049e70834cf33790a28643ab058b507b35cBen Chengint
25225b3c049e70834cf33790a28643ab058b507b35cBen Chengmain (int argc, char *argv[])
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set locale.  */
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  setlocale (LC_ALL, "");
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the message catalog.  */
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  textdomain (PACKAGE_TARNAME);
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Parse and process arguments.  */
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int remaining;
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Before we start tell the ELF library which version we are using.  */
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_version (EV_CURRENT);
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now process all the files given at the command line.  */
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool only_one = remaining + 1 == argc;
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Open the file.  */
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int fd = open (argv[remaining], O_RDONLY);
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (fd == -1)
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, errno, gettext ("cannot open input file"));
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      process_file (fd, argv[remaining], only_one);
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      close (fd);
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (++remaining < argc);
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return error_message_count != 0;
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle program arguments.  */
29025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t
29125b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_opt (int key, char *arg,
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   struct argp_state *state __attribute__ ((unused)))
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void add_dump_section (const char *name, bool implicit)
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    struct section_argument *a = xmalloc (sizeof *a);
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    a->arg = name;
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    a->next = NULL;
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    a->implicit = implicit;
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    struct section_argument ***tailp
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    **tailp = a;
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *tailp = &a->next;
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (key)
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'a':
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_file_header = true;
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_program_header = true;
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_relocations = true;
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_header = true;
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_symbol_table = true;
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_version_info = true;
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_dynamic_table = true;
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_groups = true;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_histogram = true;
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_arch = true;
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_notes = true;
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      implicit_debug_sections |= section_exception;
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (".strtab", true);
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (".dynstr", true);
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (".comment", true);
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'A':
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_arch = true;
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'd':
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_dynamic_table = true;
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'e':
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_debug_sections |= section_exception;
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'g':
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_groups = true;
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'h':
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_file_header = true;
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'I':
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_histogram = true;
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'l':
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_program_header = true;
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'n':
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_notes = true;
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'r':
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_relocations = true;
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     break;
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'S':
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_header = true;
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 's':
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_symbol_table = true;
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'V':
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_version_info = true;
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'c':
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_archive_index = true;
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'w':
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (arg == NULL)
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections = section_all;
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "abbrev") == 0)
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_abbrev;
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "aranges") == 0)
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_aranges;
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "ranges") == 0)
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_debug_sections |= section_ranges;
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  implicit_debug_sections |= section_info;
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_frame;
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "info") == 0)
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_info;
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "loc") == 0)
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_debug_sections |= section_loc;
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  implicit_debug_sections |= section_info;
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "line") == 0)
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_line;
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "pubnames") == 0)
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_pubnames;
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "str") == 0)
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_str;
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "macinfo") == 0)
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_macinfo;
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "exception") == 0)
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_exception;
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "gdb_index") == 0)
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_gdb_index;
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   arg);
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE,
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     program_invocation_short_name);
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  exit (1);
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'p':
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (arg == NULL)
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_string_sections = true;
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Fall through.  */
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'x':
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (arg, false);
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'N':
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_address_names = false;
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ARGP_KEY_NO_ARGS:
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs (gettext ("Missing file name.\n"), stderr);
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto do_argp_help;
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ARGP_KEY_FINI:
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (! any_control_option && ! print_archive_index)
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs (gettext ("No operation specified.\n"), stderr);
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	do_argp_help:
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE,
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     program_invocation_short_name);
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  exit (EXIT_FAILURE);
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'W':			/* Ignored.  */
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ARGP_ERR_UNKNOWN;
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the version information.  */
45825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
45925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("\
46325b3c049e70834cf33790a28643ab058b507b35cBen ChengCopyright (C) %s Red Hat, Inc.\n\
46425b3c049e70834cf33790a28643ab058b507b35cBen ChengThis is free software; see the source for copying conditions.  There is NO\n\
46525b3c049e70834cf33790a28643ab058b507b35cBen Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng"), "2012");
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Check if the file is an archive, and if so dump its index.  */
47225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
47325b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_archive_index (int fd, const char *fname, bool only_one)
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create an `Elf' descriptor.  */
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf == NULL)
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   elf_errmsg (-1));
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_kind (elf) == ELF_K_AR)
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!only_one)
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("\n%s:\n\n", fname);
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  dump_archive_index (elf, fname);
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0,
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("'%s' is not an archive, cannot print archive index"),
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       fname);
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Now we can close the descriptor.  */
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_end (elf) != 0)
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("error while closing Elf descriptor: %s"),
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Trivial callback used for checking if we opened an archive.  */
50125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
50225b3c049e70834cf33790a28643ab058b507b35cBen Chengcount_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       void **userdata __attribute__ ((unused)),
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       const char *name __attribute__ ((unused)),
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       Dwarf_Addr base __attribute__ ((unused)),
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       void *arg)
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*(bool *) arg)
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return DWARF_CB_ABORT;
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *(bool *) arg = true;
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return DWARF_CB_OK;
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51425b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct process_dwflmod_args
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int fd;
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool only_one;
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
52125b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_dwflmod (Dwfl_Module *dwflmod,
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 void **userdata __attribute__ ((unused)),
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 const char *name __attribute__ ((unused)),
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 Dwarf_Addr base __attribute__ ((unused)),
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 void *arg)
52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct process_dwflmod_args *a = arg;
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Print the file name.  */
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!a->only_one)
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *fname;
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("\n%s:\n\n", fname);
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  process_elf_file (dwflmod, a->fd);
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return DWARF_CB_OK;
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Stub libdwfl callback, only the ELF handle already open is ever used.  */
54425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
54525b3c049e70834cf33790a28643ab058b507b35cBen Chengfind_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   void **userdata __attribute__ ((unused)),
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   const char *modname __attribute__ ((unused)),
54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Dwarf_Addr base __attribute__ ((unused)),
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   const char *file_name __attribute__ ((unused)),
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   const char *debuglink_file __attribute__ ((unused)),
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   GElf_Word debuglink_crc __attribute__ ((unused)),
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   char **debuginfo_file_name __attribute__ ((unused)))
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return -1;
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process one input file.  */
55825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
55925b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_file (int fd, const char *fname, bool only_one)
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_archive_index)
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    check_archive_index (fd, fname, only_one);
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!any_control_option)
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Duplicate an fd for dwfl_report_offline to swallow.  */
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int dwfl_fd = dup (fd);
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (dwfl_fd < 0))
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, errno, "dup");
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Use libdwfl in a trivial way to open the libdw handle for us.
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     This takes care of applying relocations to DWARF data in ET_REL files.  */
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const Dwfl_Callbacks callbacks =
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .section_address = dwfl_offline_section_address,
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .find_debuginfo = find_no_debuginfo
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwfl *dwfl = dwfl_begin (&callbacks);
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (dwfl != NULL))
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Let 0 be the logical address of the file (or first in archive).  */
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    dwfl->offline_next_address = 0;
58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct stat64 st;
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (fstat64 (dwfl_fd, &st) != 0)
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, errno, gettext ("cannot stat input file"));
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (unlikely (st.st_size == 0))
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("input file is empty"));
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("failed reading '%s': %s"),
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       fname, dwfl_errmsg (-1));
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      close (dwfl_fd);		/* Consumed on success, not on failure.  */
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dwfl_report_end (dwfl, NULL, NULL);
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (only_one)
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool seen = false;
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Process the one or more modules gleaned from this file.  */
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  dwfl_end (dwfl);
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process one ELF file.  */
61525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
61625b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_elf_file (Dwfl_Module *dwflmod, int fd)
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr dwflbias;
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr ehdr_mem;
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr == NULL)
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    elf_error:
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Ebl *ebl = ebl_openbackend (elf);
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ebl == NULL))
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ebl_error:
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, errno, gettext ("cannot create EBL handle"));
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Determine the number of sections.  */
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot determine number of sections: %s"),
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   elf_errmsg (-1));
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Determine the number of phdrs.  */
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot determine number of program headers: %s"),
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   elf_errmsg (-1));
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     and may have applied relocation to some sections.
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     So we need to get a fresh Elf handle on the file to display those.  */
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool print_unrelocated = (print_section_header
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    || print_relocations
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    || dump_data_sections != NULL
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    || print_notes);
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *pure_elf = NULL;
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Ebl *pure_ebl = ebl;
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_type == ET_REL && print_unrelocated)
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Read the file afresh.  */
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off64_t aroff = elf_getaroff (elf);
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (aroff > 0)
66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Archive member.  */
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (void) elf_rand (pure_elf, aroff);
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_end (pure_elf);
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  pure_elf = armem;
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (pure_elf == NULL)
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto elf_error;
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      pure_ebl = ebl_openbackend (pure_elf);
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (pure_ebl == NULL)
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto ebl_error;
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_file_header)
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_ehdr (ebl, ehdr);
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_section_header)
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_shdr (pure_ebl, ehdr);
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_program_header)
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_phdr (ebl, ehdr);
68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_section_groups)
68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_scngrp (ebl);
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_dynamic_table)
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_dynamic (ebl);
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_relocations)
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_relocs (pure_ebl, ehdr);
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_histogram)
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    handle_hash (ebl);
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_symbol_table)
69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_symtab (ebl, SHT_DYNSYM);
69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_version_info)
69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_verinfo (ebl);
69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_symbol_table)
70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_symtab (ebl, SHT_SYMTAB);
70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_arch)
70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_liblist (ebl);
70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_arch)
70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_attributes (ebl, ehdr);
70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dump_data_sections != NULL)
70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    dump_data (pure_ebl);
70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (string_sections != NULL)
70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    dump_strings (ebl);
70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((print_debug_sections | implicit_debug_sections) != 0)
71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_debug (dwflmod, ebl, ehdr);
71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_notes)
71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    handle_notes (pure_ebl, ehdr);
71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_string_sections)
71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_strings (ebl);
71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ebl_closebackend (ebl);
71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (pure_ebl != ebl)
71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ebl_closebackend (pure_ebl);
72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf_end (pure_elf);
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print file type.  */
72725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
72825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_file_type (unsigned short int e_type)
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (e_type <= ET_CORE))
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      static const char *const knowntypes[] =
73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("NONE (None)"),
73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("REL (Relocatable file)"),
73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("EXEC (Executable file)"),
73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("DYN (Shared object file)"),
73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("CORE (Core file)")
73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      };
74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext (knowntypes[e_type]));
74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("OS Specific: (%x)\n"),  e_type);
74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("Processor Specific: (%x)\n"),  e_type);
74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts ("???");
74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print ELF header.  */
75225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
75325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (" %02hhx", ehdr->e_ident[cnt]);
75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n  Class:                             %s\n"),
76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : "\?\?\?");
76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Data:                              %s\n"),
76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? "2's complement, little endian"
76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? "2's complement, big endian" : "\?\?\?");
76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Ident Version:                     %hhd %s\n"),
77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_VERSION],
77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : "(\?\?\?)");
77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char buf[512];
77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  OS/ABI:                            %s\n"),
77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  ABI Version:                       %hhd\n"),
78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_ABIVERSION]);
78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("  Type:                              "), stdout);
78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_file_type (ehdr->e_type);
78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Machine:                           %s\n"), ebl->name);
78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Version:                           %d %s\n"),
78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_version,
78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_entry);
79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_phoff, gettext ("(bytes into file)"));
79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_shoff, gettext ("(bytes into file)"));
79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Flags:                             %s\n"),
80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ehsize, gettext ("(bytes)"));
80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_phentsize, gettext ("(bytes)"));
80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Number of program headers entries: %" PRId16),
81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_phnum);
81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_phnum == PN_XNUM)
81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL)
81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint32_t) shdr->sh_info);
81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked (gettext (" ([0] not available)"), stdout);
82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputc_unlocked ('\n', stdout);
82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_shentsize, gettext ("(bytes)"));
82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Number of section headers entries: %" PRId16),
82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_shnum);
82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_shnum == 0)
82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL)
83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint32_t) shdr->sh_size);
83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked (gettext (" ([0] not available)"), stdout);
83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputc_unlocked ('\n', stdout);
83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL)
84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* We managed to get the zeroth section.  */
84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (uint32_t) shdr->sh_link);
84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  buf[sizeof (buf) - 1] = '\0';
85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      buf);
85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ehdr->e_shstrndx);
86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
86425b3c049e70834cf33790a28643ab058b507b35cBen Chengget_visibility_type (int value)
86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (value)
86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_DEFAULT:
86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "DEFAULT";
87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_INTERNAL:
87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "INTERNAL";
87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_HIDDEN:
87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "HIDDEN";
87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_PROTECTED:
87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "PROTECTED";
87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "???";
87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the section headers.  */
88325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
88425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cnt;
88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! print_file_header)
89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
89125b3c049e70834cf33790a28643ab058b507b35cBen ChengThere are %d section headers, starting at offset %#" PRIx64 ":\n\
89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\n"),
89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ehdr->e_shnum, ehdr->e_shoff);
89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (gettext ("Section Headers:"));
90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (cnt = 0; cnt < shnum; ++cnt)
90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (scn == NULL))
91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the section header.  */
91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (shdr == NULL))
91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char flagbuf[20];
92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *cp = flagbuf;
92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_WRITE)
92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'W';
92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_ALLOC)
92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'A';
92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_EXECINSTR)
92925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'X';
93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_MERGE)
93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'M';
93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_STRINGS)
93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'S';
93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_INFO_LINK)
93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'I';
93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_LINK_ORDER)
93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'L';
93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_OS_NONCONFORMING)
93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'N';
94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_GROUP)
94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'G';
94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_TLS)
94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'T';
94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_ORDERED)
94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'O';
94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_EXCLUDE)
94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'E';
94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *cp = '\0';
94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[128];
95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      " %2" PRId64 "\n",
95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cnt,
95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ?: "<corrupt>",
95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_addralign);
96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputc_unlocked ('\n', stdout);
96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the program header.  */
97025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
97125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_phnum == 0)
97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* No program header, this is OK in relocatable objects.  */
97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (gettext ("Program Headers:"));
97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("\
98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("\
98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Process all program headers.  */
98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool has_relro = false;
98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr relro_from = 0;
98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr relro_to = 0;
98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < phnum; ++cnt)
99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[128];
99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr mem;
99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If for some reason the header cannot be returned show this.  */
99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (phdr == NULL))
99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  puts ("  ???");
99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_offset,
100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_filesz,
100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_memsz,
101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_flags & PF_R ? 'R' : ' ',
101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_flags & PF_W ? 'W' : ' ',
101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_flags & PF_X ? 'E' : ' ',
101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_align);
101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (phdr->p_type == PT_INTERP)
101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We can show the user the name of the interpreter.  */
101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t maxsize;
101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (filedata != NULL && phdr->p_offset < maxsize)
102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    filedata + phdr->p_offset);
102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (phdr->p_type == PT_GNU_RELRO)
102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  has_relro = true;
102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  relro_from = phdr->p_vaddr;
102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  relro_to = relro_from + phdr->p_memsz;
103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_shnum == 0)
103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* No sections in the file.  Punt.  */
103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < phnum; ++cnt)
104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Print the segment number.  */
104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("   %2.2zu     ", cnt);
104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr phdr_mem;
105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This must not happen.  */
105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (phdr == NULL))
105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Iterate over the sections.  */
105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool in_relro = false;
105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool in_ro = false;
106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t inner = 1; inner < shnum; ++inner)
106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This should not happen.  */
106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (scn == NULL))
106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   elf_errmsg (-1));
106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Get the section header.  */
106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr shdr_mem;
107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (shdr == NULL))
107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, 0,
107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   gettext ("cannot get section header: %s"),
107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   elf_errmsg (-1));
107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_size > 0
107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Compare allocated sections by VMA, unallocated
107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 sections by file offset.  */
107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (shdr->sh_flags & SHF_ALLOC
108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? (shdr->sh_addr >= phdr->p_vaddr
108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     && (shdr->sh_addr + shdr->sh_size
108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 <= phdr->p_vaddr + phdr->p_memsz))
108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : (shdr->sh_offset >= phdr->p_offset
108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     && (shdr->sh_offset + shdr->sh_size
108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 <= phdr->p_offset + phdr->p_filesz))))
108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (has_relro && !in_relro
108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && shdr->sh_addr >= relro_from
108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && shdr->sh_addr + shdr->sh_size <= relro_to)
109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (" [RELRO:", stdout);
109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  in_relro = true;
109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked ("]", stdout);
109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  in_relro =  false;
109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (has_relro && in_relro
110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       && shdr->sh_addr + shdr->sh_size > relro_to)
110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		fputs_unlocked ("] <RELRO:", stdout);
110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (!in_ro)
110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      fputs_unlocked (" [RO:", stdout);
110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      in_ro = true;
110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Determine the segment this section is part of.  */
111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t cnt2;
111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Phdr *phdr2 = NULL;
111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  for (cnt2 = 0; cnt2 < phnum; ++cnt2)
111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      GElf_Phdr phdr2_mem;
111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  && shdr->sh_addr >= phdr2->p_vaddr
112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  && (shdr->sh_addr + shdr->sh_size
112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      <= phdr2->p_vaddr + phdr2->p_memsz))
112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			break;
112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (cnt2 < phnum)
112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  fputs_unlocked (" [RO:", stdout);
113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  in_ro = true;
113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  fputs_unlocked ("]", stdout);
113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  in_ro = false;
113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (" %s",
114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Signal that this sectin is only partially covered.  */
114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (has_relro && in_relro
114725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       && shdr->sh_addr + shdr->sh_size > relro_to)
114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (">", stdout);
115025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  in_relro =  false;
115125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
115225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
115325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
115425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (in_relro || in_ro)
115525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked ("]", stdout);
115625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Finish the line.  */
115825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputc_unlocked ('\n', stdout);
115925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
116025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
116125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
116225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
116325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
116425b3c049e70834cf33790a28643ab058b507b35cBen Chengsection_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
116525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
116625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
116725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
116825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
116925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
117025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
117125b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
117225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
117325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
117425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
117525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
117625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
117725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr symshdr_mem;
117825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
117925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
118025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
118125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
118225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || symdata == NULL)
118325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
118425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
118525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
118625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
118725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
118825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
118925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
119025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
119225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Sym sym_mem;
119425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf ((grpref[0] & GRP_COMDAT)
119525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? ngettext ("\
119625b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
119725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      "\
119825b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
119925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      data->d_size / sizeof (Elf32_Word) - 1)
120025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : ngettext ("\
120125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
120225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
120325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      data->d_size / sizeof (Elf32_Word) - 1),
120425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn),
120525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
120625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, symshdr->sh_link,
120725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
120825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: gettext ("<INVALID SYMBOL>"),
120925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data->d_size / sizeof (Elf32_Word) - 1);
121025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
121125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
121225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
121325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr grpshdr_mem;
121425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
121525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 &grpshdr_mem);
121625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
121725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *str;
121825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  [%2u] %s\n",
121925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      grpref[cnt],
122025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      grpshdr != NULL
122125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
122225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ? str : gettext ("<INVALID SECTION>"));
122325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
122425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
122525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
122625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
122725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
122825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_scngrp (Ebl *ebl)
122925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
123025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find all relocation sections and handle them.  */
123125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
123225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
123325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
123425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
123525b3c049e70834cf33790a28643ab058b507b35cBen Cheng       /* Handle the section if it is a symbol table.  */
123625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
123725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
123825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
123925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == SHT_GROUP)
124025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	handle_scngrp (ebl, scn, shdr);
124125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
124225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
124325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags
124625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
124725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int mask;
124825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *str;
124925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} dt_flags[] =
125025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
125125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_ORIGIN, "ORIGIN" },
125225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_SYMBOLIC, "SYMBOLIC" },
125325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_TEXTREL, "TEXTREL" },
125425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_BIND_NOW, "BIND_NOW" },
125525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_STATIC_TLS, "STATIC_TLS" }
125625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
125725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
125825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
125925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags dt_flags_1[] =
126025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
126125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NOW, "NOW" },
126225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_GLOBAL, "GLOBAL" },
126325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_GROUP, "GROUP" },
126425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NODELETE, "NODELETE" },
126525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_LOADFLTR, "LOADFLTR" },
126625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_INITFIRST, "INITFIRST" },
126725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NOOPEN, "NOOPEN" },
126825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_ORIGIN, "ORIGIN" },
126925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_DIRECT, "DIRECT" },
127025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_TRANS, "TRANS" },
127125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_INTERPOSE, "INTERPOSE" },
127225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NODEFLIB, "NODEFLIB" },
127325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NODUMP, "NODUMP" },
127425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_CONFALT, "CONFALT" },
127525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_ENDFILTEE, "ENDFILTEE" },
127625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_DISPRELDNE, "DISPRELDNE" },
127725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_DISPRELPND, "DISPRELPND" },
127825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
127925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
128025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
128125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags dt_feature_1[] =
128225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
128325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DTF_1_PARINIT, "PARINIT" },
128425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DTF_1_CONFEXP, "CONFEXP" }
128525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
128625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_feature_1 = (sizeof (dt_feature_1)
128725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  / sizeof (dt_feature_1[0]));
128825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
128925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags dt_posflag_1[] =
129025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
129125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_P1_LAZYLOAD, "LAZYLOAD" },
129225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_P1_GROUPPERM, "GROUPPERM" }
129325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
129425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_posflag_1 = (sizeof (dt_posflag_1)
129525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  / sizeof (dt_posflag_1[0]));
129625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
129725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
129825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
129925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_flags (int class, GElf_Xword d_val, const struct flags *flags,
130025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		int nflags)
130125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
130225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool first = true;
130325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int cnt;
130425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
130525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (cnt = 0; cnt < nflags; ++cnt)
130625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (d_val & flags[cnt].mask)
130725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
130825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (!first)
130925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar_unlocked (' ');
131025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked (flags[cnt].str, stdout);
131125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	d_val &= ~flags[cnt].mask;
131225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	first = false;
131325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
131425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (d_val != 0)
131625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
131725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!first)
131825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	putchar_unlocked (' ');
131925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
132025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
132125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
132225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  putchar_unlocked ('\n');
132325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
132425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
132525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
132625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
132725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_flags (int class, GElf_Xword d_val)
132825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
132925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_flags, ndt_flags);
133025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
133125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
133425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_flags_1 (int class, GElf_Xword d_val)
133525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
133625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_flags_1, ndt_flags_1);
133725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
133825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
134125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_feature_1 (int class, GElf_Xword d_val)
134225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
134325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_feature_1, ndt_feature_1);
134425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
134525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
134825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_posflag_1 (int class, GElf_Xword d_val)
134925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
135025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
135125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
135225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
135325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
135425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
135525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
135625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
135725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
135825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr glink;
135925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data;
136025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cnt;
136125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
136225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
136425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  data = elf_getdata (scn, NULL);
136525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
136625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
136725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
136925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
137025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
137125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
137225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
137425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
137525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
137625b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
137725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_size / shdr->sh_entsize),
137825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
137925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
138025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
138125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (int) shdr->sh_link,
138225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx,
138325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
138425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &glink)->sh_name));
138525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("  Type              Value\n"), stdout);
138625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
138825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
138925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Dyn dynmem;
139025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
139125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dyn == NULL)
139225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
139325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[64];
139525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  %-17s ",
139625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
139725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (dyn->d_tag)
139925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
140025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_NULL:
140125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_DEBUG:
140225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_BIND_NOW:
140325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_TEXTREL:
140425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* No further output.  */
140525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputc_unlocked ('\n', stdout);
140625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
140725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_NEEDED:
140925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Shared library: [%s]\n"),
141025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
141125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
141225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
141325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SONAME:
141425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Library soname: [%s]\n"),
141525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
141625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
141725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
141825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RPATH:
141925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Library rpath: [%s]\n"),
142025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
142125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
142225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
142325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RUNPATH:
142425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Library runpath: [%s]\n"),
142525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
142625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
142725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
142825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_PLTRELSZ:
142925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELASZ:
143025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_STRSZ:
143125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELSZ:
143225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELAENT:
143325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SYMENT:
143425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELENT:
143525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_PLTPADSZ:
143625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_MOVEENT:
143725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_MOVESZ:
143825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_INIT_ARRAYSZ:
143925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FINI_ARRAYSZ:
144025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SYMINSZ:
144125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SYMINENT:
144225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_GNU_CONFLICTSZ:
144325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_GNU_LIBLISTSZ:
144425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
144525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
144625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
144725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_VERDEFNUM:
144825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_VERNEEDNUM:
144925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELACOUNT:
145025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELCOUNT:
145125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
145225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
145325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
145425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_PLTREL:;
145525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
145625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						      NULL, 0);
145725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  puts (tagname ?: "???");
145825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
145925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FLAGS:
146125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_flags (class, dyn->d_un.d_val);
146225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
146325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FLAGS_1:
146525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_flags_1 (class, dyn->d_un.d_val);
146625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
146725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FEATURE_1:
146925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_feature_1 (class, dyn->d_un.d_val);
147025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
147125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
147225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_POSFLAG_1:
147325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_posflag_1 (class, dyn->d_un.d_val);
147425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
147525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
147625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
147725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%#0*" PRIx64 "\n",
147825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
147925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
148025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
148125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
148225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
148325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
148425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
148525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the dynamic segment.  */
148625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
148725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dynamic (Ebl *ebl)
148825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
148925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < phnum; ++i)
149025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
149125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr phdr_mem;
149225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
149325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
149425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
149525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
149625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
149725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr shdr_mem;
149825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
149925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
150025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_dynamic (ebl, scn, shdr);
150125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
150225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
150325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
150425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
150525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print relocations.  */
150825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
150925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
151025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
151125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find all relocation sections and handle them.  */
151225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
151325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
151425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
151525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
151625b3c049e70834cf33790a28643ab058b507b35cBen Cheng       /* Handle the section if it is a symbol table.  */
151725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
151825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
151925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
152025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (shdr != NULL))
152125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
152225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_REL)
152325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_relocs_rel (ebl, ehdr, scn, shdr);
152425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_RELA)
152525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_relocs_rela (ebl, ehdr, scn, shdr);
152625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
152725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
152825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
152925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle a relocation section.  */
153225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
153325b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
153425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
153525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
153625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int nentries = shdr->sh_size / shdr->sh_entsize;
153725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
153925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
154025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
154125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
154225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the symbol table information.  */
154425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
154525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr symshdr_mem;
154625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
154725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
154825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header of the section the relocations are for.  */
155025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr destshdr_mem;
155125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
155225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &destshdr_mem);
155325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
155425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
155525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
155625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
155725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_offset);
155825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
155925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
156025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
156125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Search for the optional extended section index table.  */
156225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndxdata = NULL;
156325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int xndxscnidx = elf_scnshndx (scn);
156425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (xndxscnidx > 0))
156525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
156625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
156725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
156825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
156925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
157025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
157125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
157225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
157325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_info != 0)
157425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (ngettext ("\
157525b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
157625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
157725b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
157825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      nentries),
157925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn),
158025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
158125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    (unsigned int) shdr->sh_info,
158225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
158325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    shdr->sh_offset,
158425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    nentries);
158525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
158625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* The .rel.dyn section does not refer to a specific section but
158725b3c049e70834cf33790a28643ab058b507b35cBen Cheng       instead of section index zero.  Do not try to print a section
158825b3c049e70834cf33790a28643ab058b507b35cBen Cheng       name.  */
158925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (ngettext ("\
159025b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
159125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
159225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
159325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      nentries),
159425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    (unsigned int) elf_ndxscn (scn),
159525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
159625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    shdr->sh_offset,
159725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    nentries);
159825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (class == ELFCLASS32
159925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? gettext ("\
160025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset      Type                 Value       Name\n")
160125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : gettext ("\
160225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset              Type                 Value               Name\n"),
160325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 stdout);
160425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
160525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int is_statically_linked = 0;
160625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = 0; cnt < nentries; ++cnt)
160725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
160825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rel relmem;
160925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
161025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (rel != NULL))
161125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
161225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char buf[128];
161325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym symmem;
161425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf32_Word xndx;
161525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
161625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    GELF_R_SYM (rel->r_info),
161725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &symmem, &xndx);
161825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (sym == NULL))
161925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
162025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* As a special case we have to handle relocations in static
162125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 executables.  This only happens for IRELATIVE relocations
162225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 (so far).  There is no symbol table.  */
162325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked == 0)
162425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
162525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Find the program header and look for a PT_INTERP entry. */
162625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_statically_linked = -1;
162725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (ehdr->e_type == ET_EXEC)
162825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
162925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      is_statically_linked = 1;
163025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
163125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      for (size_t inner = 0; inner < phnum; ++inner)
163225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
163325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr phdr_mem;
163425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
163525b3c049e70834cf33790a28643ab058b507b35cBen Cheng							  &phdr_mem);
163625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  if (phdr != NULL && phdr->p_type == PT_INTERP)
163725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    {
163825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      is_statically_linked = -1;
163925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
164025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    }
164125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
164225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
164325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
164425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
164525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked > 0 && shdr->sh_link == 0)
164625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("\
164725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-20s %*s  %s\n",
164825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
164925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
165025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
165125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
165225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
165325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
165425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
165525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, "",
165625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
165725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
165825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
165925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
166025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
166125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
166225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
166325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
166425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
166525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
166625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SYMBOL"),
166725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) GELF_R_SYM (rel->r_info));
166825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
166925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
167025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
167125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
167225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    likely (ebl_reloc_type_check (ebl,
167325b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  GELF_R_TYPE (rel->r_info)))
167425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Avoid the leading R_ which isn't carrying any
167525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       information.  */
167625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
167725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   buf, sizeof (buf)) + 2
167825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    : gettext ("<INVALID RELOC>"),
167925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
168025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
168125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
168225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
168325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
168425b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   sym->st_shndx == SHN_XINDEX
168525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   ? xndx : sym->st_shndx),
168625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       &destshdr_mem);
168725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
168825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (destshdr == NULL))
168925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
169025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
169125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
169225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
169325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
169425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
169525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
169625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
169725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SECTION"),
169825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) (sym->st_shndx == SHN_XINDEX
169925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    ? xndx : sym->st_shndx));
170025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
170125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
170225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
170325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
170425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
170525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
170625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
170725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
170825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
170925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, sym->st_value,
171025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
171125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
171225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
171325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
171425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
171525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
171625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
171725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle a relocation section.  */
171825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
171925b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
172025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
172125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
172225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int nentries = shdr->sh_size / shdr->sh_entsize;
172325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
172425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
172525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
172625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
172725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
172825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
172925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the symbol table information.  */
173025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
173125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr symshdr_mem;
173225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
173325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
173425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
173525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header of the section the relocations are for.  */
173625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr destshdr_mem;
173725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
173825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &destshdr_mem);
173925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
174025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
174125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
174225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
174325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_offset);
174425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
174525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
174625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
174725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Search for the optional extended section index table.  */
174825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndxdata = NULL;
174925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int xndxscnidx = elf_scnshndx (scn);
175025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (xndxscnidx > 0))
175125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
175225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
175325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
175425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
175525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
175625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
175725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
175825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
175925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
176025b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
176125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
176225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
176325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    nentries),
176425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn),
176525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
176625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_info,
176725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
176825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
176925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  nentries);
177025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (class == ELFCLASS32
177125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? gettext ("\
177225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset      Type            Value       Addend Name\n")
177325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : gettext ("\
177425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset              Type            Value               Addend Name\n"),
177525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  stdout);
177625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
177725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int is_statically_linked = 0;
177825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = 0; cnt < nentries; ++cnt)
177925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
178025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rela relmem;
178125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
178225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (rel != NULL))
178325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
178425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char buf[64];
178525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym symmem;
178625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf32_Word xndx;
178725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
178825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    GELF_R_SYM (rel->r_info),
178925b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &symmem, &xndx);
179025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
179125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (sym == NULL))
179225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
179325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* As a special case we have to handle relocations in static
179425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 executables.  This only happens for IRELATIVE relocations
179525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 (so far).  There is no symbol table.  */
179625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked == 0)
179725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
179825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Find the program header and look for a PT_INTERP entry. */
179925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_statically_linked = -1;
180025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (ehdr->e_type == ET_EXEC)
180125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
180225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      is_statically_linked = 1;
180325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
180425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      for (size_t inner = 0; inner < phnum; ++inner)
180525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
180625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr phdr_mem;
180725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
180825b3c049e70834cf33790a28643ab058b507b35cBen Cheng							  &phdr_mem);
180925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  if (phdr != NULL && phdr->p_type == PT_INTERP)
181025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    {
181125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      is_statically_linked = -1;
181225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
181325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    }
181425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
181525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
181625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
181725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
181825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked > 0 && shdr->sh_link == 0)
181925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("\
182025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
182125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
182225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
182325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
182425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
182525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
182625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
182725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
182825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, "",
182925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			rel->r_addend,
183025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
183125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
183225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
183325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
183425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
183525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
183625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
183725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
183825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
183925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
184025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SYMBOL"),
184125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) GELF_R_SYM (rel->r_info));
184225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
184325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
184425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("\
184525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
184625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
184725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    likely (ebl_reloc_type_check (ebl,
184825b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  GELF_R_TYPE (rel->r_info)))
184925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Avoid the leading R_ which isn't carrying any
185025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       information.  */
185125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
185225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   buf, sizeof (buf)) + 2
185325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    : gettext ("<INVALID RELOC>"),
185425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
185525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    rel->r_addend,
185625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
185725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
185825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
185925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
186025b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   sym->st_shndx == SHN_XINDEX
186125b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   ? xndx : sym->st_shndx),
186225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       &destshdr_mem);
186325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
186425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (shdr == NULL))
186525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
186625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
186725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
186825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
186925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
187025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
187125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
187225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
187325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SECTION"),
187425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) (sym->st_shndx == SHN_XINDEX
187525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    ? xndx : sym->st_shndx));
187625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
187725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("\
187825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
187925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
188025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
188125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
188225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
188325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
188425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
188525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
188625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, sym->st_value,
188725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			rel->r_addend,
188825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
188925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
189025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
189125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
189225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
189325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
189425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
189525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the program header.  */
189625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
189725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_symtab (Ebl *ebl, int type)
189825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
189925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the symbol table(s).  For this we have to search through the
190025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     section table.  */
190125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
190225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
190325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
190425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
190525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the section if it is a symbol table.  */
190625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
190725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
190825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
190925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
191025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	handle_symtab (ebl, scn, shdr);
191125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
191225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
191325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
191425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
191525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
191625b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
191725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
191825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *versym_data = NULL;
191925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *verneed_data = NULL;
192025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *verdef_data = NULL;
192125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndx_data = NULL;
192225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
192325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word verneed_stridx = 0;
192425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word verdef_stridx = 0;
192525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
192625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
192725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
192825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
192925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
193025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
193125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find out whether we have other sections we might need.  */
193225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *runscn = NULL;
193325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
193425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
193525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr runshdr_mem;
193625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
193725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
193825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (runshdr != NULL))
193925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
194025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (runshdr->sh_type == SHT_GNU_versym
194125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && runshdr->sh_link == elf_ndxscn (scn))
194225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Bingo, found the version information.  Now get the data.  */
194325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    versym_data = elf_getdata (runscn, NULL);
194425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (runshdr->sh_type == SHT_GNU_verneed)
194525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
194625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is the information about the needed versions.  */
194725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verneed_data = elf_getdata (runscn, NULL);
194825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verneed_stridx = runshdr->sh_link;
194925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
195025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (runshdr->sh_type == SHT_GNU_verdef)
195125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
195225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is the information about the defined versions.  */
195325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verdef_data = elf_getdata (runscn, NULL);
195425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verdef_stridx = runshdr->sh_link;
195525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
195625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
195725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && runshdr->sh_link == elf_ndxscn (scn))
195825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Extended section index.  */
195925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    xndx_data = elf_getdata (runscn, NULL);
196025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
196125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
196225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
196325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
196425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
196525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
196625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
196725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
196825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
196925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now we can compute the number of entries in the section.  */
197025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int nsyms = data->d_size / (class == ELFCLASS32
197125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       ? sizeof (Elf32_Sym)
197225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       : sizeof (Elf64_Sym));
197325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
197425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
197525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
197625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    nsyms),
197725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
197825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
197925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr glink;
198025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
198125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    " %lu local symbols  String table: [%2u] '%s'\n",
198225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_info),
198325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned long int) shdr->sh_info,
198425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
198525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx,
198625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
198725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &glink)->sh_name));
198825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
198925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (class == ELFCLASS32
199025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? gettext ("\
199125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
199225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : gettext ("\
199325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
199425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  stdout);
199525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
199625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
199725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
199825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char typebuf[64];
199925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char bindbuf[64];
200025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char scnbuf[64];
200125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf32_Word xndx;
200225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Sym sym_mem;
200325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
200425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
200525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (sym == NULL))
200625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
200725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
200825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Determine the real section index.  */
200925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (sym->st_shndx != SHN_XINDEX))
201025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	xndx = sym->st_shndx;
201125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
201225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
201325b3c049e70834cf33790a28643ab058b507b35cBen Cheng%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
201425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cnt,
201525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      class == ELFCLASS32 ? 8 : 16,
201625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      sym->st_value,
201725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      sym->st_size,
201825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
201925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    typebuf, sizeof (typebuf)),
202025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
202125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       bindbuf, sizeof (bindbuf)),
202225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
202325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
202425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				sizeof (scnbuf), NULL, shnum),
202525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
202625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
202725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (versym_data != NULL)
202825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
202925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Get the version information.  */
203025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Versym versym_mem;
203125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
203225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
203325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
203425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
203525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bool is_nobits = false;
203625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bool check_def = xndx != SHN_UNDEF;
203725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
203825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
203925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
204025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Shdr symshdr_mem;
204125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Shdr *symshdr =
204225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
204325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
204425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_nobits = (symshdr != NULL
204525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       && symshdr->sh_type == SHT_NOBITS);
204625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
204725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
204825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_nobits || ! check_def)
204925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
205025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* We must test both.  */
205125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux vernaux_mem;
205225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux *vernaux = NULL;
205325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t vn_offset = 0;
205425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
205525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verneed verneed_mem;
205625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
205725b3c049e70834cf33790a28643ab058b507b35cBen Cheng							   &verneed_mem);
205825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (verneed != NULL)
205925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
206025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      size_t vna_offset = vn_offset;
206125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
206225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      vernaux = gelf_getvernaux (verneed_data,
206325b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 vna_offset += verneed->vn_aux,
206425b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 &vernaux_mem);
206525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      while (vernaux != NULL
206625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     && vernaux->vna_other != *versym
206725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     && vernaux->vna_next != 0)
206825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
206925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* Update the offset.  */
207025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  vna_offset += vernaux->vna_next;
207125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
207225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  vernaux = (vernaux->vna_next == 0
207325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     ? NULL
207425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     : gelf_getvernaux (verneed_data,
207525b3c049e70834cf33790a28643ab058b507b35cBen Cheng							vna_offset,
207625b3c049e70834cf33790a28643ab058b507b35cBen Cheng							&vernaux_mem));
207725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
207825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
207925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      /* Check whether we found the version.  */
208025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (vernaux != NULL && vernaux->vna_other == *versym)
208125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Found it.  */
208225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			break;
208325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
208425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      vn_offset += verneed->vn_next;
208525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      verneed = (verneed->vn_next == 0
208625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 ? NULL
208725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 : gelf_getverneed (verneed_data, vn_offset,
208825b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    &verneed_mem));
208925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
209025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
209125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (vernaux != NULL && vernaux->vna_other == *versym)
209225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
209325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf ("@%s (%u)",
209425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      elf_strptr (ebl->elf, verneed_stridx,
209525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  vernaux->vna_name),
209625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      (unsigned int) vernaux->vna_other);
209725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      check_def = 0;
209825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
209925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else if (unlikely (! is_nobits))
210025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    error (0, 0, gettext ("bad dynamic symbol"));
210125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
210225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    check_def = 1;
210325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
210425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
210525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (check_def && *versym != 0x8001)
210625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
210725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* We must test both.  */
210825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t vd_offset = 0;
210925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
211025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verdef verdef_mem;
211125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
211225b3c049e70834cf33790a28643ab058b507b35cBen Cheng							&verdef_mem);
211325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (verdef != NULL)
211425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
211525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (verdef->vd_ndx == (*versym & 0x7fff))
211625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Found the definition.  */
211725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			break;
211825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
211925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      vd_offset += verdef->vd_next;
212025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      verdef = (verdef->vd_next == 0
212125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				? NULL
212225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				: gelf_getverdef (verdef_data, vd_offset,
212325b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  &verdef_mem));
212425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
212525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
212625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (verdef != NULL)
212725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
212825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      GElf_Verdaux verdaux_mem;
212925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      GElf_Verdaux *verdaux
213025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			= gelf_getverdaux (verdef_data,
213125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   vd_offset + verdef->vd_aux,
213225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   &verdaux_mem);
213325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
213425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (verdaux != NULL)
213525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
213625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				elf_strptr (ebl->elf, verdef_stridx,
213725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    verdaux->vda_name));
213825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
213925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
214025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
214125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
214225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
214325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar_unlocked ('\n');
214425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
214525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
214625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
214725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
214825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print version information.  */
214925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
215025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_verinfo (Ebl *ebl)
215125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
215225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the version information sections.  For this we have to
215325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     search through the section table.  */
215425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
215525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
215625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
215725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
215825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the section if it is part of the versioning handling.  */
215925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
216025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
216125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
216225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (shdr != NULL))
216325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
216425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_GNU_verneed)
216525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_verneed (ebl, scn, shdr);
216625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_GNU_verdef)
216725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_verdef (ebl, scn, shdr);
216825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_GNU_versym)
216925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_versym (ebl, scn, shdr);
217025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
217125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
217225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
217325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
217425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
217525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
217625b3c049e70834cf33790a28643ab058b507b35cBen Chengget_ver_flags (unsigned int flags)
217725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
217825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static char buf[32];
217925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *endp;
218025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
218125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (flags == 0)
218225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return gettext ("none");
218325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
218425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (flags & VER_FLG_BASE)
218525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    endp = stpcpy (buf, "BASE ");
218625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
218725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    endp = buf;
218825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
218925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (flags & VER_FLG_WEAK)
219025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
219125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp != buf)
219225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	endp = stpcpy (endp, "| ");
219325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
219425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      endp = stpcpy (endp, "WEAK ");
219525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
219625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
219725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
219825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
219925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
220025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      buf[sizeof (buf) - 1] = '\0';
220125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
220225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
220325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return buf;
220425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
220525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
220625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
220725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
220825b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
220925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
221025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
221125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
221225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
221325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
221425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
221525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
221625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
221725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
221825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
221925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
222025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
222125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
222225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
222325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr glink;
222425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
222525b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
222625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
222725b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
222825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_info),
222925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
223025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
223125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
223225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
223325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
223425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx,
223525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
223625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &glink)->sh_name));
223725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
223825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int offset = 0;
223925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = shdr->sh_info; --cnt >= 0; )
224025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
224125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the data at the next offset.  */
224225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verneed needmem;
224325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
224425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (need == NULL))
224525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
224625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
224725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
224825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset, (unsigned short int) need->vn_version,
224925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
225025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (unsigned short int) need->vn_cnt);
225125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
225225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int auxoffset = offset + need->vn_aux;
225325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
225425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
225525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Vernaux auxmem;
225625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
225725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (aux == NULL))
225825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
225925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
226025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
226125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset,
226225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
226325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_ver_flags (aux->vna_flags),
226425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (unsigned short int) aux->vna_other);
226525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
226625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  auxoffset += aux->vna_next;
226725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
226825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
226925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Find the next offset.  */
227025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += need->vn_next;
227125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
227225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
227325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
227425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
227525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
227625b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
227725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
227825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
227925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
228025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
228125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
228225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
228325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
228425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
228525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
228625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
228725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
228825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
228925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
229025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr glink;
229125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
229225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
229325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
229425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
229525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_info),
229625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
229725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
229825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_info,
229925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
230025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
230125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
230225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx,
230325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
230425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &glink)->sh_name));
230525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
230625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int offset = 0;
230725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = shdr->sh_info; --cnt >= 0; )
230825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
230925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the data at the next offset.  */
231025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdef defmem;
231125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
231225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (def == NULL))
231325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
231425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
231525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int auxoffset = offset + def->vd_aux;
231625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdaux auxmem;
231725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
231825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (aux == NULL))
231925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
232025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
232125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
232225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
232325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset, def->vd_version,
232425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      get_ver_flags (def->vd_flags),
232525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      def->vd_ndx,
232625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      def->vd_cnt,
232725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
232825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
232925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      auxoffset += aux->vda_next;
233025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
233125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
233225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
233325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (aux == NULL))
233425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
233525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
233625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("  %#06x: Parent %d: %s\n"),
233725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset, cnt2,
233825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
233925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
234025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  auxoffset += aux->vda_next;
234125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
234225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
234325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Find the next offset.  */
234425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += def->vd_next;
234525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
234625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
234725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
234825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
234925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
235025b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
235125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
235225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
235325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char **vername;
235425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char **filename;
235525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
235625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
235725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
235825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
235925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
236025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
236125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
236225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
236325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
236425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
236525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
236625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
236725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We have to find the version definition section and extract the
236825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     version names.  */
236925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *defscn = NULL;
237025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *needscn = NULL;
237125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
237225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *verscn = NULL;
237325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
237425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
237525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr vershdr_mem;
237625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
237725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
237825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (vershdr != NULL))
237925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
238025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (vershdr->sh_type == SHT_GNU_verdef)
238125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    defscn = verscn;
238225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (vershdr->sh_type == SHT_GNU_verneed)
238325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    needscn = verscn;
238425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
238525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
238625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
238725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nvername;
238825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (defscn != NULL || needscn != NULL)
238925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
239025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We have a version information (better should have).  Now get
239125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 the version names.  First find the maximum version number.  */
239225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      nvername = 0;
239325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (defscn != NULL)
239425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
239525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Run through the version definitions and find the highest
239625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     index.  */
239725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
239825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *defdata;
239925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr defshdrmem;
240025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *defshdr;
240125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
240225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defdata = elf_getdata (defscn, NULL);
240325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defdata == NULL))
240425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
240525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
240625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defshdr = gelf_getshdr (defscn, &defshdrmem);
240725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defshdr == NULL))
240825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
240925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
241025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
241125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
241225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef defmem;
241325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef *def;
241425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
241525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
241625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      def = gelf_getverdef (defdata, offset, &defmem);
241725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (def == NULL))
241825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
241925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
242025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
242125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
242225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += def->vd_next;
242325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
242425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
242525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (needscn != NULL)
242625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
242725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
242825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *needdata;
242925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr needshdrmem;
243025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *needshdr;
243125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
243225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  needdata = elf_getdata (needscn, NULL);
243325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (needdata == NULL))
243425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
243525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
243625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  needshdr = gelf_getshdr (needscn, &needshdrmem);
243725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (needshdr == NULL))
243825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
243925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
244025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
244125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
244225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed needmem;
244325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed *need;
244425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int auxoffset;
244525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int cnt2;
244625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
244725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
244825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      need = gelf_getverneed (needdata, offset, &needmem);
244925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (need == NULL))
245025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
245125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
245225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Run through the auxiliary entries.  */
245325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      auxoffset = offset + need->vn_aux;
245425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
245525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
245625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux auxmem;
245725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux *aux;
245825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
245925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
246025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (aux == NULL))
246125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    break;
246225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
246325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  nvername = MAX (nvername,
246425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  (size_t) (aux->vna_other & 0x7fff));
246525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
246625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset += aux->vna_next;
246725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
246825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
246925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += need->vn_next;
247025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
247125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
247225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
247325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is the number of versions we know about.  */
247425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++nvername;
247525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
247625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Allocate the array.  */
247725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      vername = (const char **) alloca (nvername * sizeof (const char *));
247825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      filename = (const char **) alloca (nvername * sizeof (const char *));
247925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
248025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Run through the data structures again and collect the strings.  */
248125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (defscn != NULL)
248225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
248325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Run through the version definitions and find the highest
248425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     index.  */
248525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
248625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *defdata;
248725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr defshdrmem;
248825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *defshdr;
248925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
249025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defdata = elf_getdata (defscn, NULL);
249125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defdata == NULL))
249225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
249325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
249425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defshdr = gelf_getshdr (defscn, &defshdrmem);
249525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defshdr == NULL))
249625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
249725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
249825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
249925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
250025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
250125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
250225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef defmem;
250325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
250425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdaux auxmem;
250525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
250625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   offset + def->vd_aux,
250725b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   &auxmem);
250825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (def == NULL || aux == NULL))
250925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
251025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
251125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      vername[def->vd_ndx & 0x7fff]
251225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
251325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      filename[def->vd_ndx & 0x7fff] = NULL;
251425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
251525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += def->vd_next;
251625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
251725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
251825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (needscn != NULL)
251925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
252025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
252125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
252225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *needdata = elf_getdata (needscn, NULL);
252325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr needshdrmem;
252425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
252525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (needdata == NULL || needshdr == NULL))
252625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
252725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
252825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
252925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
253025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
253125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed needmem;
253225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
253325b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    &needmem);
253425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (need == NULL))
253525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
253625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
253725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Run through the auxiliary entries.  */
253825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int auxoffset = offset + need->vn_aux;
253925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
254025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
254125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux auxmem;
254225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
254325b3c049e70834cf33790a28643ab058b507b35cBen Cheng						       &auxmem);
254425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (aux == NULL))
254525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    break;
254625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
254725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  vername[aux->vna_other & 0x7fff]
254825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
254925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  filename[aux->vna_other & 0x7fff]
255025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
255125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
255225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset += aux->vna_next;
255325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
255425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
255525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += need->vn_next;
255625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
255725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
255825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
255925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
256025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
256125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      vername = NULL;
256225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      nvername = 1;
256325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      filename = NULL;
256425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
256525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
256625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Print the header.  */
256725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr glink;
256825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
256925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
257025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
257125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
257225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_size / shdr->sh_entsize),
257325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
257425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
257525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (int) (shdr->sh_size / shdr->sh_entsize),
257625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
257725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
257825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
257925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx,
258025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
258125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &glink)->sh_name));
258225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
258325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now we can finally look at the actual contents of this section.  */
258425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
258525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
258625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cnt % 2 == 0)
258725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("\n %4d:", cnt);
258825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
258925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Versym symmem;
259025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
259125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (sym == NULL)
259225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
259325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
259425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (*sym)
259525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
259625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ssize_t n;
259725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 0:
259825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (gettext ("   0 *local*                     "),
259925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  stdout);
260025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
260125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
260225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 1:
260325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (gettext ("   1 *global*                    "),
260425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  stdout);
260525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
260625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
260725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
260825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  n = printf ("%4d%c%s",
260925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
261025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (unsigned int) (*sym & 0x7fff) < nvername
261125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      ? vername[*sym & 0x7fff] : "???");
261225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((unsigned int) (*sym & 0x7fff) < nvername
261325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && filename[*sym & 0x7fff] != NULL)
261425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    n += printf ("(%s)", filename[*sym & 0x7fff]);
261525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s", MAX (0, 33 - (int) n), " ");
261625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
261725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
261825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
261925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  putchar_unlocked ('\n');
262025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
262125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
262225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
262325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
262425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
262525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 uint_fast32_t maxlength, Elf32_Word nbucket,
262625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
262725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
262825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
262925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
263025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
263125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ++counts[lengths[cnt]];
263225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
263325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr glink;
263425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
263525b3c049e70834cf33790a28643ab058b507b35cBen Cheng\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",
263625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
263725b3c049e70834cf33790a28643ab058b507b35cBen Cheng\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",
263825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    nbucket),
263925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
264025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
264125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (int) nbucket,
264225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
264325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_addr,
264425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
264525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
264625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx,
264725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
264825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &glink)->sh_name));
264925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
265025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (extrastr != NULL)
265125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    fputs (extrastr, stdout);
265225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
265325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (nbucket > 0))
265425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
265525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t success = 0;
265625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
265725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* xgettext:no-c-format */
265825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs_unlocked (gettext ("\
265925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Length  Number  % of total  Coverage\n"), stdout);
266025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
266125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      counts[0], (counts[0] * 100.0) / nbucket);
266225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
266325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t nzero_counts = 0;
266425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
266525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
266625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  nzero_counts += counts[cnt] * cnt;
266725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\
266825b3c049e70834cf33790a28643ab058b507b35cBen Cheng%7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
266925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
267025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (nzero_counts * 100.0) / nsyms);
267125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
267225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
267325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf32_Word acc = 0;
267425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
267525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
267625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  acc += cnt;
267725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  success += counts[cnt] * acc;
267825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
267925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
268025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
268125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Average number of tests:   successful lookup: %f\n\
268225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  unsuccessful lookup: %f\n"),
268325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (double) success / (double) nzero_counts,
268425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (double) nzero_counts / (double) nbucket);
268525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
268625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
268725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (counts);
268825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
268925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
269025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
269125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This function handles the traditional System V-style hash table format.  */
269225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
269325b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
269425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
269525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
269625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
269725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
269825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
269925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
270025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
270125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
270225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
270325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
270425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
270525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
270625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
270725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
270825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
270925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
271025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t maxlength = 0;
271125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nsyms = 0;
271225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
271325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
271425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf32_Word inner = bucket[cnt];
271525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (inner > 0 && inner < nchain)
271625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
271725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++nsyms;
271825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (maxlength < ++lengths[cnt])
271925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++maxlength;
272025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
272125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  inner = chain[inner];
272225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
272325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
272425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
272525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
272625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   lengths, NULL);
272725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
272825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (lengths);
272925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
273025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
273125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
273225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This function handles the incorrect, System V-style hash table
273325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   format some 64-bit architectures use.  */
273425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
273525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
273625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
273725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
273825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
273925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
274025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
274125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
274225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
274325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
274425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
274525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
274625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
274725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
274825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
274925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
275025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
275125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
275225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t maxlength = 0;
275325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nsyms = 0;
275425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
275525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
275625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf64_Xword inner = bucket[cnt];
275725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (inner > 0 && inner < nchain)
275825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
275925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++nsyms;
276025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (maxlength < ++lengths[cnt])
276125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++maxlength;
276225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
276325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  inner = chain[inner];
276425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
276525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
276625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
276725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
276825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   lengths, NULL);
276925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
277025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (lengths);
277125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
277225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
277325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
277425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This function handles the GNU-style hash table format.  */
277525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
277625b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
277725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
277825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
277925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
278025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
278125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
278225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
278325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
278425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
278525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
278625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
278725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
278825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
278925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Next comes the size of the bitmap.  It's measured in words for
279025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
279125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     64 bit archs.  */
279225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
279325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (gelf_getclass (ebl->elf) == ELFCLASS64)
279425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    bitmask_words *= 2;
279525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
279625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
279725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
279825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
279925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
280025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
280125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
280225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
280325b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    + nbucket];
280425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
280525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Compute distribution of chain lengths.  */
280625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t maxlength = 0;
280725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nsyms = 0;
280825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
280925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (bucket[cnt] != 0)
281025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
281125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	Elf32_Word inner = bucket[cnt] - symbias;
281225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	do
281325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
281425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++nsyms;
281525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (maxlength < ++lengths[cnt])
281625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ++maxlength;
281725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
281825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	while ((chain[inner++] & 1) == 0);
281925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
282025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
282125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Count bits in bitmask.  */
282225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nbits = 0;
282325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
282425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
282525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast32_t word = bitmask[cnt];
282625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
282725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
282825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
282925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
283025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
283125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
283225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
283325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
283425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *str;
283525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (asprintf (&str, gettext ("\
283625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Symbol Bias: %u\n\
283725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
283825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (unsigned int) symbias,
283925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  bitmask_words * sizeof (Elf32_Word),
284025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  ((nbits * 100 + 50)
284125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   / (uint_fast32_t) (bitmask_words
284225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      * sizeof (Elf32_Word) * 8)),
284325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (unsigned int) shift) == -1))
284425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
284525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
284625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
284725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   lengths, str);
284825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
284925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (str);
285025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (lengths);
285125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
285225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
285325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
285425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Find the symbol table(s).  For this we have to search through the
285525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   section table.  */
285625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
285725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_hash (Ebl *ebl)
285825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
285925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
286025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
286125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
286225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
286325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
286425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
286525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
286625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
286725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
286825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the section if it is a symbol table.  */
286925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
287025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
287125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
287225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (shdr != NULL))
287325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
287425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_HASH)
287525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
287625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
287725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
287825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
287925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_sysv_hash (ebl, scn, shdr, shstrndx);
288025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
288125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_GNU_HASH)
288225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
288325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
288425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
288525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
288625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
288725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
288825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
288925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_liblist (Ebl *ebl)
289025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
289125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the library list sections.  For this we have to search
289225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     through the section table.  */
289325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
289425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
289525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
289625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
289725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
289825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
289925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
290025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
290125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
290225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
290325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
290425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
290525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
290625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
290725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
290825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int nentries = shdr->sh_size / shdr->sh_entsize;
290925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (ngettext ("\
291025b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
291125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    "\
291225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
291325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    nentries),
291425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn),
291525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
291625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_offset,
291725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  nentries);
291825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
291925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *data = elf_getdata (scn, NULL);
292025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (data == NULL)
292125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
292225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
292325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  puts (gettext ("\
292425b3c049e70834cf33790a28643ab058b507b35cBen Cheng       Library                       Time Stamp          Checksum Version Flags"));
292525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
292625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (int cnt = 0; cnt < nentries; ++cnt)
292725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
292825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Lib lib_mem;
292925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
293025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (lib == NULL))
293125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
293225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
293325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      time_t t = (time_t) lib->l_time_stamp;
293425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct tm *tm = gmtime (&t);
293525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (tm == NULL))
293625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
293725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
293825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
293925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
294025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
294125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      tm->tm_hour, tm->tm_min, tm->tm_sec,
294225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (unsigned int) lib->l_checksum,
294325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (unsigned int) lib->l_version,
294425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (unsigned int) lib->l_flags);
294525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
294625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
294725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
294825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
294925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
295025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
295125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
295225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
295325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the object attributes sections.  For this we have to search
295425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     through the section table.  */
295525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
295625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
295725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
295825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
295925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
296025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
296125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
296225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
296325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
296425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
296525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
296625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
296725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
296825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
296925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   && (shdr->sh_type != SHT_ARM_ATTRIBUTES
297025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       || ehdr->e_machine != EM_ARM)))
297125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
297225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
297325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
297425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nObject attributes section [%2zu] '%s' of %" PRIu64
297525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " bytes at offset %#0" PRIx64 ":\n"),
297625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_ndxscn (scn),
297725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
297825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_size, shdr->sh_offset);
297925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
298025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
298125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (data == NULL)
298225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return;
298325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
298425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *p = data->d_buf;
298525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
298625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (*p++ != 'A'))
298725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return;
298825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
298925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
299025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
299125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      inline size_t left (void)
299225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
299325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return (const unsigned char *) data->d_buf + data->d_size - p;
299425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
299525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
299625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (left () >= 4)
299725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
299825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint32_t len;
299925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (&len, p, sizeof len);
300025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
300125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
300225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (len);
300325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
300425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (len > left ()))
300525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
300625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
300725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *name = p + sizeof len;
300825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  p += len;
300925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
301025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned const char *q = memchr (name, '\0', len);
301125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (q == NULL))
301225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
301325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++q;
301425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
301525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
301625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
301725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type != SHT_GNU_ATTRIBUTES
301825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || (q - name == sizeof "gnu"
301925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && !memcmp (name, "gnu", sizeof "gnu")))
302025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (q < p)
302125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
302225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		const unsigned char *const sub = q;
302325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
302425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		unsigned int subsection_tag;
302525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		get_uleb128 (subsection_tag, q);
302625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (q >= p))
302725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
302825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
302925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		uint32_t subsection_len;
303025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
303125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
303225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
303325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		memcpy (&subsection_len, q, sizeof subsection_len);
303425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
303525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
303625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  CONVERT (subsection_len);
303725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
303825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (p - sub < (ptrdiff_t) subsection_len))
303925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
304025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
304125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		const unsigned char *r = q + sizeof subsection_len;
304225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		q = sub + subsection_len;
304325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
304425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		switch (subsection_tag)
304525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
304625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  default:
304725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("    %-4u %12" PRIu32 "\n"),
304825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    subsection_tag, subsection_len);
304925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    break;
305025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
305125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  case 1:	/* Tag_File */
305225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("    File: %11" PRIu32 "\n"),
305325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    subsection_len);
305425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
305525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    while (r < q)
305625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      {
305725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			unsigned int tag;
305825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			get_uleb128 (tag, r);
305925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (unlikely (r >= q))
306025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  break;
306125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
306225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			uint64_t value = 0;
306325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const char *string = NULL;
306425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (tag == 32 || (tag & 1) == 0)
306525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
306625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    get_uleb128 (value, r);
306725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (r > q)
306825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
306925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
307025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (tag == 32 || (tag & 1) != 0)
307125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
307225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    r = memchr (r, '\0', q - r);
307325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (r == NULL)
307425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
307525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    ++r;
307625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
307725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
307825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const char *tag_name = NULL;
307925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const char *value_name = NULL;
308025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_check_object_attribute (ebl, (const char *) name,
308125b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    tag, value,
308225b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    &tag_name, &value_name);
308325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
308425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (tag_name != NULL)
308525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
308625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (tag == 32)
308725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %s: %" PRId64 ", %s\n"),
308825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag_name, value, string);
308925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    else if (string == NULL && value_name == NULL)
309025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %s: %" PRId64 "\n"),
309125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag_name, value);
309225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    else
309325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %s: %s\n"),
309425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag_name, string ?: value_name);
309525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
309625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			else
309725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
309825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    assert (tag != 32);
309925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (string == NULL)
310025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %u: %" PRId64 "\n"),
310125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag, value);
310225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    else
310325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %u: %s\n"),
310425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag, string);
310525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
310625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      }
310725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
310825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
310925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
311025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
311125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
311225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
311325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
311425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic char *
311525b3c049e70834cf33790a28643ab058b507b35cBen Chengformat_dwarf_addr (Dwfl_Module *dwflmod,
311625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   int address_size, Dwarf_Addr address)
311725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
311825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* See if there is a name we can give for this address.  */
311925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Sym sym;
312025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *name = print_address_names
312125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL;
312225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (name != NULL)
312325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    sym.st_value = address - sym.st_value;
312425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
312525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Relativize the address.  */
312625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int n = dwfl_module_relocations (dwflmod);
312725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
312825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
312925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* In an ET_REL file there is a section name to refer to.  */
313025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *scn = (i < 0 ? NULL
313125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     : dwfl_module_relocation_info (dwflmod, i, NULL));
313225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
313325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *result;
313425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((name != NULL
313525b3c049e70834cf33790a28643ab058b507b35cBen Cheng       ? (sym.st_value != 0
313625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? (scn != NULL
313725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? (address_size == 0
313825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
313925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
314025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    scn, address, name, sym.st_value)
314125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
314225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
314325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    scn, 2 + address_size * 2, address,
314425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    name, sym.st_value))
314525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : (address_size == 0
314625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
314725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
314825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    address, name, sym.st_value)
314925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
315025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
315125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    2 + address_size * 2, address,
315225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    name, sym.st_value)))
315325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : (scn != NULL
315425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? (address_size == 0
315525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
315625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#" PRIx64 " <%s>"),
315725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    scn, address, name)
315825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
315925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#0*" PRIx64 " <%s>"),
316025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    scn, 2 + address_size * 2, address, name))
316125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : (address_size == 0
316225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
316325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#" PRIx64 " <%s>"),
316425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    address, name)
316525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
316625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#0*" PRIx64 " <%s>"),
316725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    2 + address_size * 2, address, name))))
316825b3c049e70834cf33790a28643ab058b507b35cBen Cheng       : (scn != NULL
316925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? (address_size == 0
317025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? asprintf (&result,
317125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 gettext ("%s+%#" PRIx64),
317225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 scn, address)
317325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : asprintf (&result,
317425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 gettext ("%s+%#0*" PRIx64),
317525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 scn, 2 + address_size * 2, address))
317625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : (address_size == 0
317725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? asprintf (&result,
317825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 "%#" PRIx64,
317925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 address)
318025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : asprintf (&result,
318125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 "%#0*" PRIx64,
318225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 2 + address_size * 2, address)))) < 0)
318325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0, _("memory exhausted"));
318425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
318525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
318625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
318725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
318825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
318925b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_tag_string (unsigned int tag)
319025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
319125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known_tags[]  =
319225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
319325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_array_type] = "array_type",
319425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_class_type] = "class_type",
319525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_entry_point] = "entry_point",
319625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_enumeration_type] = "enumeration_type",
319725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_formal_parameter] = "formal_parameter",
319825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_imported_declaration] = "imported_declaration",
319925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_label] = "label",
320025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_lexical_block] = "lexical_block",
320125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_member] = "member",
320225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_pointer_type] = "pointer_type",
320325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_reference_type] = "reference_type",
320425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_compile_unit] = "compile_unit",
320525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_string_type] = "string_type",
320625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_structure_type] = "structure_type",
320725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_subroutine_type] = "subroutine_type",
320825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_typedef] = "typedef",
320925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_union_type] = "union_type",
321025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_unspecified_parameters] = "unspecified_parameters",
321125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_variant] = "variant",
321225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_common_block] = "common_block",
321325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_common_inclusion] = "common_inclusion",
321425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_inheritance] = "inheritance",
321525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_inlined_subroutine] = "inlined_subroutine",
321625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_module] = "module",
321725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
321825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_set_type] = "set_type",
321925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_subrange_type] = "subrange_type",
322025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_with_stmt] = "with_stmt",
322125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_access_declaration] = "access_declaration",
322225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_base_type] = "base_type",
322325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_catch_block] = "catch_block",
322425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_const_type] = "const_type",
322525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_constant] = "constant",
322625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_enumerator] = "enumerator",
322725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_file_type] = "file_type",
322825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_friend] = "friend",
322925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_namelist] = "namelist",
323025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_namelist_item] = "namelist_item",
323125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_packed_type] = "packed_type",
323225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_subprogram] = "subprogram",
323325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_template_type_parameter] = "template_type_parameter",
323425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_template_value_parameter] = "template_value_parameter",
323525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_thrown_type] = "thrown_type",
323625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_try_block] = "try_block",
323725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_variant_part] = "variant_part",
323825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_variable] = "variable",
323925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_volatile_type] = "volatile_type",
324025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_dwarf_procedure] = "dwarf_procedure",
324125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_restrict_type] = "restrict_type",
324225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_interface_type] = "interface_type",
324325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_namespace] = "namespace",
324425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_imported_module] = "imported_module",
324525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_unspecified_type] = "unspecified_type",
324625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_partial_unit] = "partial_unit",
324725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_imported_unit] = "imported_unit",
324825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_mutable_type] = "mutable_type",
324925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_condition] = "condition",
325025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_shared_type] = "shared_type",
325125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_type_unit] = "type_unit",
325225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_rvalue_reference_type] = "rvalue_reference_type",
325325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_TAG_template_alias] = "template_alias",
325425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
325525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned int nknown_tags = (sizeof (known_tags)
325625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    / sizeof (known_tags[0]));
325725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static char buf[40];
325825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *result = NULL;
325925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
326025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (tag < nknown_tags))
326125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    result = known_tags[tag];
326225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
326325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (result == NULL))
326425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* There are a few known extensions.  */
326525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    switch (tag)
326625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
326725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_MIPS_loop:
326825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_loop";
326925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
327025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
327125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_format_label:
327225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "format_label";
327325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
327425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
327525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_function_template:
327625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "function_template";
327725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
327825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
327925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_class_template:
328025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "class_template";
328125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
328225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
328325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_GNU_BINCL:
328425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_BINCL";
328525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
328625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
328725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_GNU_EINCL:
328825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_EINCL";
328925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
329025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
329125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_GNU_template_template_param:
329225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_template_template_param";
329325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
329425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
329525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_GNU_template_parameter_pack:
329625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_template_parameter_pack";
329725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
329825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
329925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_GNU_formal_parameter_pack:
330025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_formal_parameter_pack";
330125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
330225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
330325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_GNU_call_site:
330425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_call_site";
330525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
330625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
330725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_TAG_GNU_call_site_parameter:
330825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_call_site_parameter";
330925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
331025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
331125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      default:
331225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (tag < DW_TAG_lo_user)
331325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
331425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	else
331525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
331625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = buf;
331725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
331825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
331925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
332025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
332125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
332225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
332325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
332425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
332525b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_attr_string (unsigned int attrnum)
332625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
332725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known_attrs[] =
332825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
332925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_sibling] = "sibling",
333025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_location] = "location",
333125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_name] = "name",
333225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_ordering] = "ordering",
333325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_subscr_data] = "subscr_data",
333425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_byte_size] = "byte_size",
333525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_bit_offset] = "bit_offset",
333625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_bit_size] = "bit_size",
333725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_element_list] = "element_list",
333825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_stmt_list] = "stmt_list",
333925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_low_pc] = "low_pc",
334025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_high_pc] = "high_pc",
334125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_language] = "language",
334225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_member] = "member",
334325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_discr] = "discr",
334425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_discr_value] = "discr_value",
334525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_visibility] = "visibility",
334625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_import] = "import",
334725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_string_length] = "string_length",
334825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_common_reference] = "common_reference",
334925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_comp_dir] = "comp_dir",
335025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_const_value] = "const_value",
335125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_containing_type] = "containing_type",
335225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_default_value] = "default_value",
335325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_inline] = "inline",
335425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_is_optional] = "is_optional",
335525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_lower_bound] = "lower_bound",
335625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_producer] = "producer",
335725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_prototyped] = "prototyped",
335825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_return_addr] = "return_addr",
335925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_start_scope] = "start_scope",
336025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_bit_stride] = "bit_stride",
336125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_upper_bound] = "upper_bound",
336225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_abstract_origin] = "abstract_origin",
336325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_accessibility] = "accessibility",
336425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_address_class] = "address_class",
336525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_artificial] = "artificial",
336625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_base_types] = "base_types",
336725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_calling_convention] = "calling_convention",
336825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_count] = "count",
336925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_data_member_location] = "data_member_location",
337025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_decl_column] = "decl_column",
337125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_decl_file] = "decl_file",
337225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_decl_line] = "decl_line",
337325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_declaration] = "declaration",
337425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_discr_list] = "discr_list",
337525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_encoding] = "encoding",
337625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_external] = "external",
337725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_frame_base] = "frame_base",
337825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_friend] = "friend",
337925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_identifier_case] = "identifier_case",
338025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_macro_info] = "macro_info",
338125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_namelist_item] = "namelist_item",
338225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_priority] = "priority",
338325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_segment] = "segment",
338425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_specification] = "specification",
338525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_static_link] = "static_link",
338625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_type] = "type",
338725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_use_location] = "use_location",
338825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_variable_parameter] = "variable_parameter",
338925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_virtuality] = "virtuality",
339025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_vtable_elem_location] = "vtable_elem_location",
339125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_allocated] = "allocated",
339225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_associated] = "associated",
339325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_data_location] = "data_location",
339425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_byte_stride] = "byte_stride",
339525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_entry_pc] = "entry_pc",
339625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_use_UTF8] = "use_UTF8",
339725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_extension] = "extension",
339825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_ranges] = "ranges",
339925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_trampoline] = "trampoline",
340025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_call_column] = "call_column",
340125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_call_file] = "call_file",
340225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_call_line] = "call_line",
340325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_description] = "description",
340425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_binary_scale] = "binary_scale",
340525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_decimal_scale] = "decimal_scale",
340625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_small] = "small",
340725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_decimal_sign] = "decimal_sign",
340825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_digit_count] = "digit_count",
340925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_picture_string] = "picture_string",
341025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_mutable] = "mutable",
341125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_threads_scaled] = "threads_scaled",
341225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_explicit] = "explicit",
341325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_object_pointer] = "object_pointer",
341425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_endianity] = "endianity",
341525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_elemental] = "elemental",
341625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_pure] = "pure",
341725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_recursive] = "recursive",
341825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_signature] = "signature",
341925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_main_subprogram] = "main_subprogram",
342025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_data_bit_offset] = "data_bit_offset",
342125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_const_expr] = "const_expr",
342225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_enum_class] = "enum_class",
342325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_AT_linkage_name] = "linkage_name",
342425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
342525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned int nknown_attrs = (sizeof (known_attrs)
342625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     / sizeof (known_attrs[0]));
342725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static char buf[40];
342825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *result = NULL;
342925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
343025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (attrnum < nknown_attrs))
343125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    result = known_attrs[attrnum];
343225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
343325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (result == NULL))
343425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* There are a few known extensions.  */
343525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    switch (attrnum)
343625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
343725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_fde:
343825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_fde";
343925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
344025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
344125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_loop_begin:
344225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_loop_begin";
344325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
344425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
344525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_tail_loop_begin:
344625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_tail_loop_begin";
344725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
344825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
344925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_epilog_begin:
345025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_epilog_begin";
345125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
345225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
345325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_loop_unroll_factor:
345425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_loop_unroll_factor";
345525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
345625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
345725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_software_pipeline_depth:
345825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_software_pipeline_depth";
345925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
346025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
346125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_linkage_name:
346225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_linkage_name";
346325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
346425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
346525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_stride:
346625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_stride";
346725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
346825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
346925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_abstract_name:
347025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_abstract_name";
347125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
347225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
347325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_clone_origin:
347425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_clone_origin";
347525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
347625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
347725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_has_inlines:
347825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_has_inlines";
347925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
348025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
348125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_stride_byte:
348225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_stride_byte";
348325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
348425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
348525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_stride_elem:
348625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_stride_elem";
348725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
348825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
348925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_ptr_dopetype:
349025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_ptr_dopetype";
349125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
349225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
349325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_allocatable_dopetype:
349425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_allocatable_dopetype";
349525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
349625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
349725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_assumed_shape_dopetype:
349825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_assumed_shape_dopetype";
349925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
350025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
350125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_MIPS_assumed_size:
350225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "MIPS_assumed_size";
350325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
350425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
350525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_sf_names:
350625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "sf_names";
350725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
350825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
350925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_src_info:
351025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "src_info";
351125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
351225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
351325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_mac_info:
351425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "mac_info";
351525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
351625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
351725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_src_coords:
351825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "src_coords";
351925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
352025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
352125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_body_begin:
352225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "body_begin";
352325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
352425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
352525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_body_end:
352625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "body_end";
352725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
352825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
352925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_vector:
353025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_vector";
353125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
353225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
353325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_guarded_by:
353425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_guarded_by";
353525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
353625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
353725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_pt_guarded_by:
353825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_pt_guarded_by";
353925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
354025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
354125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_guarded:
354225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_guarded";
354325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
354425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
354525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_pt_guarded:
354625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_pt_guarded";
354725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
354825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
354925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_locks_excluded:
355025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_locks_excluded";
355125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
355225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
355325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_exclusive_locks_required:
355425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_exclusive_locks_required";
355525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
355625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
355725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_shared_locks_required:
355825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_shared_locks_required";
355925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
356025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
356125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_odr_signature:
356225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_odr_signature";
356325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
356425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
356525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_template_name:
356625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_template_name";
356725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
356825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
356925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_call_site_value:
357025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_call_site_value";
357125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
357225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
357325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_call_site_data_value:
357425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_call_site_data_value";
357525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
357625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
357725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_call_site_target:
357825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_call_site_target";
357925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
358025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
358125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_call_site_target_clobbered:
358225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_call_site_target_clobbered";
358325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
358425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
358525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_tail_call:
358625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_tail_call";
358725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
358825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
358925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_all_tail_call_sites:
359025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_all_tail_call_sites";
359125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
359225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
359325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_all_call_sites:
359425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_all_call_sites";
359525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
359625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
359725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      case DW_AT_GNU_all_source_call_sites:
359825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = "GNU_all_source_call_sites";
359925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
360025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
360125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      default:
360225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (attrnum < DW_AT_lo_user)
360325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
360425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    attrnum);
360525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	else
360625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
360725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    attrnum);
360825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = buf;
360925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
361025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
361125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
361225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
361325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
361425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
361525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
361625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
361725b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_form_string (unsigned int form)
361825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
361925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known_forms[] =
362025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
362125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_addr] = "addr",
362225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_block2] = "block2",
362325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_block4] = "block4",
362425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_data2] = "data2",
362525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_data4] = "data4",
362625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_data8] = "data8",
362725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_string] = "string",
362825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_block] = "block",
362925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_block1] = "block1",
363025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_data1] = "data1",
363125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_flag] = "flag",
363225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_sdata] = "sdata",
363325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_strp] = "strp",
363425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_udata] = "udata",
363525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_ref_addr] = "ref_addr",
363625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_ref1] = "ref1",
363725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_ref2] = "ref2",
363825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_ref4] = "ref4",
363925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_ref8] = "ref8",
364025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_ref_udata] = "ref_udata",
364125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_indirect] = "indirect",
364225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_sec_offset] = "sec_offset",
364325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_exprloc] = "exprloc",
364425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_flag_present] = "flag_present",
364525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_FORM_ref_sig8] = "ref_sig8",
364625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
364725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned int nknown_forms = (sizeof (known_forms)
364825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     / sizeof (known_forms[0]));
364925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static char buf[40];
365025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *result = NULL;
365125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
365225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (form < nknown_forms))
365325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    result = known_forms[form];
365425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
365525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (result == NULL))
365625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
365725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      snprintf (buf, sizeof buf, gettext ("unknown form %#" PRIx64),
365825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) form);
365925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = buf;
366025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
366125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
366225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
366325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
366425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
366525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
366625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
366725b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_lang_string (unsigned int lang)
366825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
366925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
367025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
367125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_C89] = "ISO C89",
367225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_C] = "C",
367325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Ada83] = "Ada83",
367425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_C_plus_plus] = "C++",
367525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Cobol74] = "Cobol74",
367625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Cobol85] = "Cobol85",
367725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Fortran77] = "Fortran77",
367825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Fortran90] = "Fortran90",
367925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Pascal83] = "Pascal83",
368025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Modula2] = "Modula2",
368125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Java] = "Java",
368225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_C99] = "ISO C99",
368325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Ada95] = "Ada95",
368425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Fortran95] = "Fortran95",
368525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_PL1] = "PL1",
368625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_Objc] = "Objective C",
368725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_ObjC_plus_plus] = "Objective C++",
368825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_UPC] = "UPC",
368925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_LANG_D] = "D",
369025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
369125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
369225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (lang < sizeof (known) / sizeof (known[0])))
369325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[lang];
369425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (lang == DW_LANG_Mips_Assembler)
369525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* This language tag is used for assembler in general.  */
369625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return "Assembler";
369725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
369825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
369925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
370025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      static char buf[30];
370125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
370225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return buf;
370325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
370425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
370525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
370625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
370725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
370825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
370925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
371025b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_inline_string (unsigned int code)
371125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
371225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
371325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
371425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_INL_not_inlined] = "not_inlined",
371525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_INL_inlined] = "inlined",
371625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_INL_declared_not_inlined] = "declared_not_inlined",
371725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_INL_declared_inlined] = "declared_inlined"
371825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
371925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
372025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
372125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
372225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
372325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
372425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
372525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
372625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
372725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
372825b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_encoding_string (unsigned int code)
372925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
373025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
373125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
373225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_void] = "void",
373325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_address] = "address",
373425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_boolean] = "boolean",
373525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_complex_float] = "complex_float",
373625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_float] = "float",
373725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_signed] = "signed",
373825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_signed_char] = "signed_char",
373925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_unsigned] = "unsigned",
374025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_unsigned_char] = "unsigned_char",
374125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_imaginary_float] = "imaginary_float",
374225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_packed_decimal] = "packed_decimal",
374325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_numeric_string] = "numeric_string",
374425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_edited] = "edited",
374525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_signed_fixed] = "signed_fixed",
374625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_unsigned_fixed] = "unsigned_fixed",
374725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ATE_decimal_float] = "decimal_float",
374825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
374925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
375025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
375125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
375225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
375325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
375425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
375525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      static char buf[30];
375625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
375725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return buf;
375825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
375925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
376025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
376125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
376225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
376325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
376425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
376525b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_access_string (unsigned int code)
376625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
376725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
376825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
376925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ACCESS_public] = "public",
377025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ACCESS_protected] = "protected",
377125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ACCESS_private] = "private"
377225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
377325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
377425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
377525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
377625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
377725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
377825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
377925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
378025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
378125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
378225b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_visibility_string (unsigned int code)
378325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
378425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
378525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
378625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_VIS_local] = "local",
378725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_VIS_exported] = "exported",
378825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_VIS_qualified] = "qualified"
378925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
379025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
379225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
379325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
379525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
379625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
379925b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_virtuality_string (unsigned int code)
380025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
380125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
380225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
380325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_VIRTUALITY_none] = "none",
380425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_VIRTUALITY_virtual] = "virtual",
380525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_VIRTUALITY_pure_virtual] = "pure_virtual"
380625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
380725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
380825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
380925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
381025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
381125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
381225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
381325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
381425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
381525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
381625b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_identifier_case_string (unsigned int code)
381725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
381825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
381925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
382025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ID_case_sensitive] = "sensitive",
382125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ID_up_case] = "up_case",
382225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ID_down_case] = "down_case",
382325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ID_case_insensitive] = "insensitive"
382425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
382525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
382625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
382725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
382825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
382925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
383025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
383125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
383225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
383325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
383425b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_calling_convention_string (unsigned int code)
383525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
383625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
383725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
383825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_CC_normal] = "normal",
383925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_CC_program] = "program",
384025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_CC_nocall] = "nocall",
384125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
384225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
384325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
384425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
384525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
384625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (code >= DW_CC_lo_user && code <= DW_CC_hi_user)
384725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
384825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      static char buf[30];
384925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user);
385025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return buf;
385125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
385225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
385325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
385425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
385525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
385625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
385725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
385825b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_ordering_string (unsigned int code)
385925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
386025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
386125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
386225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ORD_row_major] = "row_major",
386325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_ORD_col_major] = "col_major"
386425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
386525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
386625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
386725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
386825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
386925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
387025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
387125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
387225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
387325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
387425b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_discr_list_string (unsigned int code)
387525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
387625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
387725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
387825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_DSC_label] = "label",
387925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_DSC_range] = "range"
388025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
388125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
388225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
388325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
388425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
388525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
388625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
388725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
388825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
388925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
389025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_block (size_t n, const void *block)
389125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
389225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (n == 0)
389325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (_("empty block"));
389425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
389525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
389625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (_("%zu byte block:"), n);
389725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *data = block;
389825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
389925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (" %02x", *data++);
390025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (--n > 0);
390125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar ('\n');
390225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
390325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
390425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
390525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
390625b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
390725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   unsigned int vers, unsigned int addrsize, unsigned int offset_size,
390825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   Dwarf_Word len, const unsigned char *data)
390925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
391025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
391125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
391225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
391325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
391425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_addr] = "addr",
391525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_deref] = "deref",
391625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const1u] = "const1u",
391725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const1s] = "const1s",
391825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const2u] = "const2u",
391925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const2s] = "const2s",
392025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const4u] = "const4u",
392125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const4s] = "const4s",
392225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const8u] = "const8u",
392325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_const8s] = "const8s",
392425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_constu] = "constu",
392525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_consts] = "consts",
392625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_dup] = "dup",
392725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_drop] = "drop",
392825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_over] = "over",
392925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_pick] = "pick",
393025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_swap] = "swap",
393125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_rot] = "rot",
393225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_xderef] = "xderef",
393325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_abs] = "abs",
393425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_and] = "and",
393525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_div] = "div",
393625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_minus] = "minus",
393725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_mod] = "mod",
393825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_mul] = "mul",
393925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_neg] = "neg",
394025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_not] = "not",
394125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_or] = "or",
394225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_plus] = "plus",
394325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_plus_uconst] = "plus_uconst",
394425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_shl] = "shl",
394525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_shr] = "shr",
394625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_shra] = "shra",
394725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_xor] = "xor",
394825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_bra] = "bra",
394925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_eq] = "eq",
395025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_ge] = "ge",
395125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_gt] = "gt",
395225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_le] = "le",
395325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lt] = "lt",
395425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_ne] = "ne",
395525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_skip] = "skip",
395625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit0] = "lit0",
395725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit1] = "lit1",
395825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit2] = "lit2",
395925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit3] = "lit3",
396025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit4] = "lit4",
396125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit5] = "lit5",
396225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit6] = "lit6",
396325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit7] = "lit7",
396425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit8] = "lit8",
396525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit9] = "lit9",
396625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit10] = "lit10",
396725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit11] = "lit11",
396825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit12] = "lit12",
396925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit13] = "lit13",
397025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit14] = "lit14",
397125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit15] = "lit15",
397225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit16] = "lit16",
397325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit17] = "lit17",
397425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit18] = "lit18",
397525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit19] = "lit19",
397625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit20] = "lit20",
397725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit21] = "lit21",
397825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit22] = "lit22",
397925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit23] = "lit23",
398025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit24] = "lit24",
398125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit25] = "lit25",
398225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit26] = "lit26",
398325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit27] = "lit27",
398425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit28] = "lit28",
398525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit29] = "lit29",
398625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit30] = "lit30",
398725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_lit31] = "lit31",
398825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg0] = "reg0",
398925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg1] = "reg1",
399025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg2] = "reg2",
399125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg3] = "reg3",
399225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg4] = "reg4",
399325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg5] = "reg5",
399425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg6] = "reg6",
399525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg7] = "reg7",
399625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg8] = "reg8",
399725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg9] = "reg9",
399825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg10] = "reg10",
399925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg11] = "reg11",
400025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg12] = "reg12",
400125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg13] = "reg13",
400225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg14] = "reg14",
400325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg15] = "reg15",
400425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg16] = "reg16",
400525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg17] = "reg17",
400625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg18] = "reg18",
400725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg19] = "reg19",
400825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg20] = "reg20",
400925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg21] = "reg21",
401025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg22] = "reg22",
401125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg23] = "reg23",
401225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg24] = "reg24",
401325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg25] = "reg25",
401425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg26] = "reg26",
401525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg27] = "reg27",
401625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg28] = "reg28",
401725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg29] = "reg29",
401825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg30] = "reg30",
401925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_reg31] = "reg31",
402025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg0] = "breg0",
402125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg1] = "breg1",
402225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg2] = "breg2",
402325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg3] = "breg3",
402425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg4] = "breg4",
402525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg5] = "breg5",
402625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg6] = "breg6",
402725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg7] = "breg7",
402825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg8] = "breg8",
402925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg9] = "breg9",
403025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg10] = "breg10",
403125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg11] = "breg11",
403225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg12] = "breg12",
403325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg13] = "breg13",
403425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg14] = "breg14",
403525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg15] = "breg15",
403625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg16] = "breg16",
403725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg17] = "breg17",
403825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg18] = "breg18",
403925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg19] = "breg19",
404025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg20] = "breg20",
404125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg21] = "breg21",
404225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg22] = "breg22",
404325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg23] = "breg23",
404425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg24] = "breg24",
404525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg25] = "breg25",
404625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg26] = "breg26",
404725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg27] = "breg27",
404825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg28] = "breg28",
404925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg29] = "breg29",
405025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg30] = "breg30",
405125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_breg31] = "breg31",
405225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_regx] = "regx",
405325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_fbreg] = "fbreg",
405425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_bregx] = "bregx",
405525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_piece] = "piece",
405625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_deref_size] = "deref_size",
405725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_xderef_size] = "xderef_size",
405825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_nop] = "nop",
405925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_push_object_address] = "push_object_address",
406025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_call2] = "call2",
406125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_call4] = "call4",
406225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_call_ref] = "call_ref",
406325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_form_tls_address] = "form_tls_address",
406425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_call_frame_cfa] = "call_frame_cfa",
406525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_bit_piece] = "bit_piece",
406625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_implicit_value] = "implicit_value",
406725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_stack_value] = "stack_value",
406825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer",
406925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_GNU_entry_value] = "GNU_entry_value",
407025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_GNU_const_type] = "GNU_const_type",
407125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_GNU_regval_type] = "GNU_regval_type",
407225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_GNU_deref_type] = "GNU_deref_type",
407325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_GNU_convert] = "GNU_convert",
407425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      [DW_OP_GNU_reinterpret] = "GNU_reinterpret",
407525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
407625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
407725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (len == 0)
407825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
407925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%*s(empty)\n", indent, "");
408025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
408125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
408225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
408325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define NEED(n)		if (len < (Dwarf_Word) (n)) goto invalid
408425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define CONSUME(n)	NEED (n); else len -= (n)
408525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
408625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word offset = 0;
408725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (len-- > 0)
408825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
408925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t op = *data++;
409025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
409125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (op)
409225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
409325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_addr:;
409425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Address operand.  */
409525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Word addr;
409625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (addrsize);
409725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (addrsize == 4)
409825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    addr = read_4ubyte_unaligned (dbg, data);
409925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
410025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
410125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert (addrsize == 8);
410225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      addr = read_8ubyte_unaligned (dbg, data);
410325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
410425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += addrsize;
410525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (addrsize);
410625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
410725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *a = format_dwarf_addr (dwflmod, 0, addr);
410825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %s\n",
410925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], a);
411025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (a);
411125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
411225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + addrsize;
411325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
411425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
411525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call_ref:
411625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Offset operand.  */
411725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (ref_size);
411825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ref_size == 4)
411925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    addr = read_4ubyte_unaligned (dbg, data);
412025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
412125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
412225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert (ref_size == 8);
412325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      addr = read_8ubyte_unaligned (dbg, data);
412425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
412525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += ref_size;
412625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (ref_size);
412725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
412825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
412925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
413025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], (uintmax_t) addr);
413125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + ref_size;
413225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
413325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
413425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_deref_size:
413525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_xderef_size:
413625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_pick:
413725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const1u:
413825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
413925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
414025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
414125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
414225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], *((uint8_t *) data));
414325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++data;
414425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  --len;
414525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 2;
414625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
414725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
414825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const2u:
414925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
415025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
415125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
415225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
415325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], read_2ubyte_unaligned (dbg, data));
415425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
415525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 2;
415625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
415725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
415825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
415925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const4u:
416025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (4);
416125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
416225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
416325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
416425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], read_4ubyte_unaligned (dbg, data));
416525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (4);
416625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 4;
416725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 5;
416825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
416925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
417025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const8u:
417125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (8);
417225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
417325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
417425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
417525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], read_8ubyte_unaligned (dbg, data));
417625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (8);
417725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 8;
417825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 9;
417925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
418025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
418125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const1s:
418225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
418325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
418425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
418525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
418625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], *((int8_t *) data));
418725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++data;
418825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  --len;
418925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 2;
419025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
419125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
419225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const2s:
419325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
419425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
419525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
419625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
419725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], read_2sbyte_unaligned (dbg, data));
419825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
419925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 2;
420025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
420125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
420225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
420325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const4s:
420425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (4);
420525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
420625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
420725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
420825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], read_4sbyte_unaligned (dbg, data));
420925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (4);
421025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 4;
421125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 5;
421225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
421325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
421425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const8s:
421525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (8);
421625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
421725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
421825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
421925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], read_8sbyte_unaligned (dbg, data));
422025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (8);
422125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 8;
422225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 9;
422325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
422425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
422525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_piece:
422625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_regx:
422725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_plus_uconst:
422825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_constu:;
422925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *start = data;
423025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t uleb;
423125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
423225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
423325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
423425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], uleb);
423525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
423625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
423725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
423825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
423925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bit_piece:
424025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
424125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t uleb2;
424225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
424325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
424425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb2, data); /* XXX check overrun */
424525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
424625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
424725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
424825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
424925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
425025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
425125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_fbreg:
425225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_breg0 ... DW_OP_breg31:
425325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_consts:
425425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
425525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int64_t sleb;
425625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
425725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (sleb, data); /* XXX check overrun */
425825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
425925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], sleb);
426025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
426125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
426225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
426325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
426425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bregx:
426525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
426625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
426725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
426825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (sleb, data); /* XXX check overrun */
426925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
427025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], uleb, sleb);
427125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
427225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
427325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
427425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
427525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call2:
427625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
427725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
427825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op],
427925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  read_2ubyte_unaligned (dbg, data));
428025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
428125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
428225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
428325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
428425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call4:
428525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (4);
428625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
428725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op],
428825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  read_4ubyte_unaligned (dbg, data));
428925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (4);
429025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 5;
429125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
429225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
429325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_skip:
429425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bra:
429525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
429625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
429725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op],
429825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
429925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
430025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 2;
430125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
430225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
430325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
430425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_implicit_value:
430525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
430625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
430725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
430825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s: ",
430925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op]);
431025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (uleb);
431125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_block (uleb, data);
431225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += uleb;
431325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
431425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
431525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
431625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
431725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_implicit_pointer:
431825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* DIE offset operand.  */
431925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
432025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (ref_size + 1);
432125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ref_size == 4)
432225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    addr = read_4ubyte_unaligned (dbg, data);
432325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
432425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
432525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert (ref_size == 8);
432625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      addr = read_8ubyte_unaligned (dbg, data);
432725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
432825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += ref_size;
432925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Byte offset operand.  */
433025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (sleb, data); /* XXX check overrun */
433125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
433225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n",
433325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (intmax_t) offset,
433425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], (uintmax_t) addr, sleb);
433525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
433625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
433725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
433825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
433925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_entry_value:
434025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Size plus expression block.  */
434125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
434225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
434325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
434425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s:\n",
434525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op]);
434625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (uleb);
434725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
434825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     addrsize, offset_size, uleb, data);
434925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += uleb;
435025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
435125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
435225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
435325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
435425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_const_type:
435525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* DIE offset, size plus block.  */
435625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
435725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
435825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
435925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint8_t usize = *(uint8_t *) data++;
436025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (usize);
436125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
436225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], uleb);
436325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_block (usize, data);
436425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += usize;
436525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
436625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
436725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
436825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
436925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_regval_type:
437025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
437125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
437225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
437325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb2, data); /* XXX check overrun */
437425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n",
437525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
437625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
437725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
437825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
437925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
438025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_deref_type:
438125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
438225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
438325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  usize = *(uint8_t *) data++;
438425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
438525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
438625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
438725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  known[op], usize, uleb);
438825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
438925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
439025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
439125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
439225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_convert:
439325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_reinterpret:
439425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
439525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
439625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (uleb, data); /* XXX check overrun */
439725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
439825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset, known[op], uleb);
439925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
440025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
440125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
440225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
440325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
440425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* No Operand.  */
440525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (op < sizeof known / sizeof known[0] && known[op] != NULL)
440625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s[%4" PRIuMAX "] %s\n",
440725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    indent, "", (uintmax_t) offset, known[op]);
440825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
440925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s[%4" PRIuMAX "] %#x\n",
441025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    indent, "", (uintmax_t) offset, op);
441125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++offset;
441225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
441325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
441425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
441525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      indent = indentrest;
441625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      continue;
441725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
441825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid:
441925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("%*s[%4" PRIuMAX "] %s  <TRUNCATED>\n"),
442025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      indent, "", (uintmax_t) offset, known[op]);
442125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
442225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
442325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
442425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
442525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
442625b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct listptr
442725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
442825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset:(64 - 3);
442925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool addr64:1;
443025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool dwarf64:1;
443125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool warned:1;
443225b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
443325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
443425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define listptr_offset_size(p)	((p)->dwarf64 ? 8 : 4)
443525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define listptr_address_size(p)	((p)->addr64 ? 8 : 4)
443625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
443725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
443825b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_listptr (const void *a, const void *b, void *arg)
443925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
444025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *name = arg;
444125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *p1 = (void *) a;
444225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *p2 = (void *) b;
444325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
444425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (p1->offset < p2->offset)
444525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
444625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (p1->offset > p2->offset)
444725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
444825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
444925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!p1->warned && !p2->warned)
445025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
445125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (p1->addr64 != p2->addr64)
445225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
445325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  p1->warned = p2->warned = true;
445425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0,
445525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 gettext ("%s %#" PRIx64 " used with different address sizes"),
445625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 name, (uint64_t) p1->offset);
445725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
445825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (p1->dwarf64 != p2->dwarf64)
445925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
446025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  p1->warned = p2->warned = true;
446125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0,
446225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 gettext ("%s %#" PRIx64 " used with different offset sizes"),
446325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 name, (uint64_t) p1->offset);
446425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
446525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
446625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
446725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
446825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
446925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
447025b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct listptr_table
447125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
447225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t n;
447325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t alloc;
447425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *table;
447525b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
447625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
447725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct listptr_table known_loclistptr;
447825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct listptr_table known_rangelistptr;
447925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
448025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
448125b3c049e70834cf33790a28643ab058b507b35cBen Chengreset_listptr (struct listptr_table *table)
448225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
448325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (table->table);
448425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  table->table = NULL;
448525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  table->n = table->alloc = 0;
448625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
448725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
448825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
448925b3c049e70834cf33790a28643ab058b507b35cBen Chengnotice_listptr (enum section_e section, struct listptr_table *table,
449025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		uint_fast8_t address_size, uint_fast8_t offset_size,
449125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		Dwarf_Off offset)
449225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
449325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_debug_sections & section)
449425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
449525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (table->n == table->alloc)
449625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
449725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (table->alloc == 0)
449825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    table->alloc = 128;
449925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
450025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    table->alloc *= 2;
450125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  table->table = xrealloc (table->table,
450225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   table->alloc * sizeof table->table[0]);
450325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
450425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
450525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct listptr *p = &table->table[table->n++];
450625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
450725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *p = (struct listptr)
450825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
450925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  .addr64 = address_size == 8,
451025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  .dwarf64 = offset_size == 8,
451125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  .offset = offset
451225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	};
451325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (p->offset == offset);
451425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
451525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
451625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
451725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
451825b3c049e70834cf33790a28643ab058b507b35cBen Chengsort_listptr (struct listptr_table *table, const char *name)
451925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
452025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (table->n > 0)
452125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    qsort_r (table->table, table->n, sizeof table->table[0],
452225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     &compare_listptr, (void *) name);
452325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
452425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
452525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool
452625b3c049e70834cf33790a28643ab058b507b35cBen Chengskip_listptr_hole (struct listptr_table *table, size_t *idxp,
452725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
452825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   ptrdiff_t offset, unsigned char **readp, unsigned char *endp)
452925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
453025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (table->n == 0)
453125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
453225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
453325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
453425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ++*idxp;
453525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
453625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *p = &table->table[*idxp];
453725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
453825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*idxp == table->n
453925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || p->offset >= (Dwarf_Off) (endp - *readp + offset))
454025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
454125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *readp = endp;
454225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext (" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
454325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset);
454425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return true;
454525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
454625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
454725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (p->offset != (Dwarf_Off) offset)
454825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
454925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *readp += p->offset - offset;
455025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext (" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
455125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset, (Dwarf_Off) p->offset - offset);
455225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return true;
455325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
455425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
455525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (address_sizep != NULL)
455625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *address_sizep = listptr_address_size (p);
455725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (offset_sizep != NULL)
455825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *offset_sizep = listptr_offset_size (p);
455925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
456025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return false;
456125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
456225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
456325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
456425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
456525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
456625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Ebl *ebl, GElf_Ehdr *ehdr,
456725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
456825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
456925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
457025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " [ Code]\n"),
457125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
457225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
457325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
457425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset = 0;
457525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (offset < dbg->sectiondata[IDX_debug_abbrev]->d_size)
457625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
457725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
457825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset);
457925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
458025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (1)
458125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
458225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t length;
458325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Abbrev abbrev;
458425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
458525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
458625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (res != 0)
458725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
458825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (res < 0))
458925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
459025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext ("\
459125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *** error while reading abbreviation: %s\n"),
459225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  dwarf_errmsg (-1));
459325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  return;
459425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
459525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
459625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is the NUL byte at the end of the section.  */
459725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ++offset;
459825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
459925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
460025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
460125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We know these calls can never fail.  */
460225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int code = dwarf_getabbrevcode (&abbrev);
460325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
460425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int has_children = dwarf_abbrevhaschildren (&abbrev);
460525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
460625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%5u] offset: %" PRId64
460725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   ", children: %s, tag: %s\n"),
460825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  code, (int64_t) offset,
460925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  has_children ? gettext ("yes") : gettext ("no"),
461025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  dwarf_tag_string (tag));
461125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
461225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t cnt = 0;
461325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int name;
461425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int form;
461525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Off enoffset;
461625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (dwarf_getabbrevattr (&abbrev, cnt,
461725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &name, &form, &enoffset) == 0)
461825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
461925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
462025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      dwarf_attr_string (name), dwarf_form_string (form),
462125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (uint64_t) enoffset);
462225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
462325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ++cnt;
462425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
462525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
462625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += length;
462725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
462825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
462925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
463025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
463125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
463225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print content of DWARF .debug_aranges section.  We fortunately do
463325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   not have to know a bit about the structure of the section, libdwarf
463425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   takes care of it.  */
463525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
463625b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
463725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
463825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     GElf_Shdr *shdr, Dwarf *dbg)
463925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
464025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Aranges *aranges;
464125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cnt;
464225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
464325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
464425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
464525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     dwarf_errmsg (-1));
464625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
464725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
464825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
464925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
465025b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
465125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
465225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
465325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    cnt),
465425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
465525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset, cnt);
465625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
465725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Compute floor(log16(cnt)).  */
465825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t tmp = cnt;
465925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int digits = 1;
466025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (tmp >= 16)
466125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
466225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++digits;
466325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      tmp >>= 4;
466425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
466525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
466625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t n = 0; n < cnt; ++n)
466725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
466825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Arange *runp = dwarf_onearange (aranges, n);
466925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (runp == NULL))
467025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
467125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
467225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return;
467325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
467425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
467525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr start;
467625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word length;
467725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off offset;
467825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
467925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
468025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" [%*zu] ???\n"), digits, n);
468125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
468225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" [%*zu] start: %0#*" PRIx64
468325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", length: %5" PRIu64 ", CU DIE offset: %6"
468425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 PRId64 "\n"),
468525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
468625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) start, (uint64_t) length, (int64_t) offset);
468725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
468825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
468925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
469025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print content of DWARF .debug_ranges section.  */
469125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
469225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_ranges_section (Dwfl_Module *dwflmod,
469325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Ebl *ebl, GElf_Ehdr *ehdr,
469425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Elf_Scn *scn, GElf_Shdr *shdr,
469525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Dwarf *dbg)
469625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
469725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
469825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
469925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
470025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
470125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
470225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
470325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
470425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
470525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
470625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
470725b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
470825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
470925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
471025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
471125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sort_listptr (&known_rangelistptr, "rangelistptr");
471225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t listptr_idx = 0;
471325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
471425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
471525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
471625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool first = true;
471725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
471825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *readp = data->d_buf;
471925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < endp)
472025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
472125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
472225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
472325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
472425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &address_size, NULL,
472525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      offset, &readp, endp))
472625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
472725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
472825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (data->d_size - offset < address_size * 2))
472925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
473025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
473125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
473225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
473325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
473425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr begin;
473525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr end;
473625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (address_size == 8)
473725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
473825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_8ubyte_unaligned_inc (dbg, readp);
473925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_8ubyte_unaligned_inc (dbg, readp);
474025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
474125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
474225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
474325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_4ubyte_unaligned_inc (dbg, readp);
474425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_4ubyte_unaligned_inc (dbg, readp);
474525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (begin == (Dwarf_Addr) (uint32_t) -1)
474625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    begin = (Dwarf_Addr) -1l;
474725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
474825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
474925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
475025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
475125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, end);
475225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
475325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
475425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
475525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (begin == 0 && end == 0) /* End of list entry.  */
475625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
475725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)
475825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  empty list\n"), offset);
475925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = true;
476025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
476125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
476225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
476325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
476425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *e = format_dwarf_addr (dwflmod, address_size, end);
476525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We have an address range entry.  */
476625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)		/* First address range entry in a list.  */
476725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  %s..%s\n"), offset, b, e);
476825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
476925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext ("           %s..%s\n"), b, e);
477025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
477125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (e);
477225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
477325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = false;
477425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
477525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
477625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
477725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
477825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define REGNAMESZ 16
477925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
478025b3c049e70834cf33790a28643ab058b507b35cBen Chengregister_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
478125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       char name[REGNAMESZ], int *bits, int *type)
478225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
478325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *set;
478425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *pfx;
478525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int ignore;
478625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
478725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 bits ?: &ignore, type ?: &ignore);
478825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (n <= 0)
478925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
479025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      snprintf (name, REGNAMESZ, "reg%u", loc->regno);
479125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (bits != NULL)
479225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*bits = loc->bits;
479325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (type != NULL)
479425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*type = DW_ATE_unsigned;
479525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      set = "??? unrecognized";
479625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
479725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
479825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
479925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (bits != NULL && *bits <= 0)
480025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*bits = loc->bits;
480125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (type != NULL && *type == DW_ATE_void)
480225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*type = DW_ATE_unsigned;
480325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
480425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
480525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return set;
480625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
480725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
480825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
480925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_cfa_program (const unsigned char *readp, const unsigned char *const endp,
481025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Dwarf_Word vma_base, unsigned int code_align,
481125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   int data_align,
481225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   unsigned int version, unsigned int ptr_size,
481325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
481425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
481525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char regnamebuf[REGNAMESZ];
481625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *regname (unsigned int regno)
481725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
481825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
481925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return regnamebuf;
482025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
482125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
482225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts ("\n   Program:");
482325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word pc = vma_base;
482425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < endp)
482525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
482625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int opcode = *readp++;
482725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
482825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (opcode < DW_CFA_advance_loc)
482925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Extended opcode.  */
483025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	switch (opcode)
483125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
483225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    uint64_t op1;
483325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    int64_t sop1;
483425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    uint64_t op2;
483525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    int64_t sop2;
483625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
483725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_nop:
483825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     nop");
483925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
484025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_set_loc:
484125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
484225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
484325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 += vma_base;
484425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     set_loc %" PRIu64 "\n", op1 * code_align);
484525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
484625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_advance_loc1:
484725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     advance_loc1 %u to %#" PRIx64 "\n",
484825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    *readp, pc += *readp * code_align);
484925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++readp;
485025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
485125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_advance_loc2:
485225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 = read_2ubyte_unaligned_inc (dbg, readp);
485325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
485425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, pc += op1 * code_align);
485525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
485625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_advance_loc4:
485725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 = read_4ubyte_unaligned_inc (dbg, readp);
485825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
485925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, pc += op1 * code_align);
486025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
486125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_offset_extended:
486225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
486325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
486425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op2, readp);
486525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
486625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\n",
486725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), op2 * data_align);
486825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
486925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_restore_extended:
487025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
487125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
487225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
487325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
487425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
487525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_undefined:
487625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
487725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
487825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
487925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
488025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_same_value:
488125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
488225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
488325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
488425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
488525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_register:
488625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
488725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
488825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op2, readp);
488925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
489025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), op2, regname (op2));
489125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
489225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_remember_state:
489325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     remember_state");
489425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
489525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_restore_state:
489625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     restore_state");
489725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
489825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa:
489925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
490025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
490125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op2, readp);
490225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
490325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), op2);
490425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
490525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_register:
490625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
490725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
490825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
490925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
491025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
491125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_offset:
491225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
491325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
491425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
491525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
491625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_expression:
491725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
491825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);	/* Length of DW_FORM_block.  */
491925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
492025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op1, readp);
492125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += op1;
492225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
492325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_expression:
492425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
492525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
492625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op2, readp);	/* Length of DW_FORM_block.  */
492725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     expression r%" PRIu64 " (%s) \n",
492825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
492925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
493025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += op2;
493125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
493225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_offset_extended_sf:
493325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
493425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
493525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_sleb128 (sop2, readp);
493625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
493725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    PRId64 "\n",
493825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), sop2 * data_align);
493925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
494025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_sf:
494125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
494225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
494325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_sleb128 (sop2, readp);
494425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
494525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), sop2 * data_align);
494625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
494725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_offset_sf:
494825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
494925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_sleb128 (sop1, readp);
495025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
495125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
495225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_val_offset:
495325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
495425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
495525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op2, readp);
495625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
495725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, op2 * data_align);
495825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
495925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_val_offset_sf:
496025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
496125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
496225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_sleb128 (sop2, readp);
496325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
496425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, sop2 * data_align);
496525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
496625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_val_expression:
496725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
496825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
496925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op2, readp);	/* Length of DW_FORM_block.  */
497025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     val_expression r%" PRIu64 " (%s)\n",
497125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
497225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp);
497325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += op2;
497425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
497525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_MIPS_advance_loc8:
497625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 = read_8ubyte_unaligned_inc (dbg, readp);
497725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
497825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, pc += op1 * code_align);
497925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
498025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_GNU_window_save:
498125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     GNU_window_save");
498225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
498325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_GNU_args_size:
498425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX overflow check
498525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (op1, readp);
498625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     args_size %" PRIu64 "\n", op1);
498725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
498825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  default:
498925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     ??? (%u)\n", opcode);
499025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
499125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
499225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (opcode < DW_CFA_offset)
499325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("     advance_loc %u to %#" PRIx64 "\n",
499425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
499525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (opcode < DW_CFA_restore)
499625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
499725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t offset;
499825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX overflow check
499925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (offset, readp);
500025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
500125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
500225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
500325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
500425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("     restore r%u (%s)\n",
500525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		opcode & 0x3f, regname (opcode & 0x3f));
500625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
500725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
500825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
500925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
501025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
501125b3c049e70834cf33790a28643ab058b507b35cBen Chengencoded_ptr_size (int encoding, unsigned int ptr_size)
501225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
501325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (encoding & 7)
501425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
501525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 2:
501625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 2;
501725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 3:
501825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 4;
501925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 4:
502025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 8;
502125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
502225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ptr_size;
502325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
502425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
502525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
502625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
502725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
502825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_encoding (unsigned int val)
502925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
503025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (val & 0xf)
503125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
503225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_absptr:
503325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("absptr", stdout);
503425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
503525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_uleb128:
503625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("uleb128", stdout);
503725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
503825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata2:
503925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("udata2", stdout);
504025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
504125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata4:
504225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("udata4", stdout);
504325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
504425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata8:
504525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("udata8", stdout);
504625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
504725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sleb128:
504825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sleb128", stdout);
504925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
505025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata2:
505125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sdata2", stdout);
505225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
505325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata4:
505425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sdata4", stdout);
505525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
505625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata8:
505725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sdata8", stdout);
505825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
505925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
506025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We did not use any of the bits after all.  */
506125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return val;
506225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
506325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
506425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return val & ~0xf;
506525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
506625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
506725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
506825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
506925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_relinfo (unsigned int val)
507025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
507125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (val & 0x70)
507225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
507325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_pcrel:
507425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("pcrel", stdout);
507525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
507625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_textrel:
507725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("textrel", stdout);
507825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
507925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_datarel:
508025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("datarel", stdout);
508125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
508225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_funcrel:
508325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("funcrel", stdout);
508425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
508525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_aligned:
508625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("aligned", stdout);
508725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
508825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
508925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return val;
509025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
509125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
509225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return val & ~0x70;
509325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
509425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
509525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
509625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
509725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_encoding_base (const char *pfx, unsigned int fde_encoding)
509825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
509925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf ("(%s", pfx);
510025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
510125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fde_encoding == DW_EH_PE_omit)
510225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts ("omit)");
510325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
510425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
510525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int w = fde_encoding;
510625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
510725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      w = print_encoding (w);
510825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
510925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (w & 0x70)
511025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
511125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (w != fde_encoding)
511225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    fputc_unlocked (' ', stdout);
511325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
511425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  w = print_relinfo (w);
511525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
511625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
511725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (w != 0)
511825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("%s%x", w != fde_encoding ? " " : "", w);
511925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
512025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (")");
512125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
512225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
512325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
512425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
512525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const unsigned char *
512625b3c049e70834cf33790a28643ab058b507b35cBen Chengread_encoded (unsigned int encoding, const unsigned char *readp,
512725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
512825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
512925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((encoding & 0xf) == DW_EH_PE_absptr)
513025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    encoding = gelf_getclass (dbg->elf) == ELFCLASS32
513125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
513225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
513325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (encoding & 0xf)
513425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
513525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_uleb128:
513625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      // XXX buffer overrun check
513725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      get_uleb128 (*res, readp);
513825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
513925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sleb128:
514025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      // XXX buffer overrun check
514125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      get_sleb128 (*res, readp);
514225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
514325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata2:
514425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 2 > endp)
514525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
514625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_2ubyte_unaligned_inc (dbg, readp);
514725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
514825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata4:
514925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 4 > endp)
515025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
515125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_4ubyte_unaligned_inc (dbg, readp);
515225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
515325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata8:
515425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 8 > endp)
515525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
515625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_8ubyte_unaligned_inc (dbg, readp);
515725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
515825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata2:
515925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 2 > endp)
516025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
516125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_2sbyte_unaligned_inc (dbg, readp);
516225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
516325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata4:
516425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 4 > endp)
516525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
516625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_4sbyte_unaligned_inc (dbg, readp);
516725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
516825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata8:
516925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 8 > endp)
517025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
517125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_8sbyte_unaligned_inc (dbg, readp);
517225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
517325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
517425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid:
517525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (1, 0,
517625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     gettext ("invalid encoding"));
517725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
517825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
517925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return readp;
518025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
518125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
518225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
518325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
518425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
518525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
518625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
518725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
518825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We know this call will succeed since it did in the caller.  */
518925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
519025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
519125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
519225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
519325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
519425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
519525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
519625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
519725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     scnname, elf_errmsg (-1));
519825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
519925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
520025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
520125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
520225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (is_eh_frame)
520325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
520425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
520525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
520625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
520725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
520825b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
520925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
521025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
521125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct cieinfo
521225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
521325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ptrdiff_t cie_offset;
521425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    const char *augmentation;
521525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    unsigned int code_alignment_factor;
521625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    unsigned int data_alignment_factor;
521725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    uint8_t address_size;
521825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    uint8_t fde_encoding;
521925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    uint8_t lsda_encoding;
522025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    struct cieinfo *next;
522125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  } *cies = NULL;
522225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
522325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
522425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = ((unsigned char *) data->d_buf
522525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					+ data->d_size);
522625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < dataend)
522725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
522825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (readp + 4 > dataend))
522925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
523025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	invalid_data:
523125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
523225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     elf_ndxscn (scn), scnname);
523325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
523425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
523525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
523625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* At the beginning there must be a CIE.  There can be multiple,
523725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 hence we test tis in a loop.  */
523825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
523925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
524025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
524125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int length = 4;
524225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (unit_length == 0xffffffff))
524325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
524425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (readp + 8 > dataend))
524525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
524625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
524725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
524825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  length = 8;
524925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
525025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
525125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (unit_length == 0))
525225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
525325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
525425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
525525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
525625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
525725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
525825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
525925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t start = readp - (unsigned char *) data->d_buf;
526025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *const cieend = readp + unit_length;
526125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (cieend > dataend || readp + 8 > dataend))
526225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
526325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
526425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off cie_id;
526525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (length == 4)
526625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
526725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cie_id = read_4ubyte_unaligned_inc (dbg, readp);
526825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!is_eh_frame && cie_id == DW_CIE_ID_32)
526925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    cie_id = DW_CIE_ID_64;
527025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
527125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
527225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	cie_id = read_8ubyte_unaligned_inc (dbg, readp);
527325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
527425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t version = 2;
527525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int code_alignment_factor;
527625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int data_alignment_factor;
527725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int fde_encoding = 0;
527825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int lsda_encoding = 0;
527925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word initial_location = 0;
528025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word vma_base = 0;
528125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
528225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
528325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
528425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  version = *readp++;
528525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *const augmentation = (const char *) readp;
528625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = memchr (readp, '\0', cieend - readp);
528725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (readp == NULL))
528825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
528925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++readp;
529025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
529125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint_fast8_t segment_size = 0;
529225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (version >= 4)
529325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
529425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (cieend - readp < 5)
529525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto invalid_data;
529625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ptr_size = *readp++;
529725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      segment_size = *readp++;
529825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
529925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
530025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX Check overflow
530125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (code_alignment_factor, readp);
530225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX Check overflow
530325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (data_alignment_factor, readp);
530425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
530525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* In some variant for unwind data there is another field.  */
530625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (strcmp (augmentation, "eh") == 0)
530725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
530825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
530925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int return_address_register;
531025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (version == 1))
531125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return_address_register = *readp++;
531225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
531325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    // XXX Check overflow
531425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    get_uleb128 (return_address_register, readp);
531525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
531625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
531725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   CIE_id:                   %" PRIu64 "\n"
531825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   version:                  %u\n"
531925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   augmentation:             \"%s\"\n",
532025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  offset, (uint64_t) unit_length, (uint64_t) cie_id,
532125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  version, augmentation);
532225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (version >= 4)
532325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("   address_size:             %u\n"
532425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "   segment_size:             %u\n",
532525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ptr_size, segment_size);
532625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("   code_alignment_factor:    %u\n"
532725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   data_alignment_factor:    %d\n"
532825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   return_address_register:  %u\n",
532925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  code_alignment_factor,
533025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  data_alignment_factor, return_address_register);
533125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
533225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (augmentation[0] == 'z')
533325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
533425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int augmentationlen;
533525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      get_uleb128 (augmentationlen, readp);
533625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
533725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (augmentationlen > (size_t) (dataend - readp))
533825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		error (1, 0, gettext ("invalid augmentation length"));
533925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
534025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const char *hdr = "Augmentation data:";
534125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const char *cp = augmentation + 1;
534225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      while (*cp != '\0')
534325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
534425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf ("   %-26s%#x ", hdr, *readp);
534525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  hdr = "";
534625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
534725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (*cp == 'R')
534825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
534925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      fde_encoding = *readp++;
535025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      print_encoding_base (gettext ("FDE address encoding: "),
535125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   fde_encoding);
535225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
535325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else if (*cp == 'L')
535425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
535525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      lsda_encoding = *readp++;
535625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      print_encoding_base (gettext ("LSDA pointer encoding: "),
535725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   lsda_encoding);
535825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
535925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else if (*cp == 'P')
536025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
536125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      /* Personality.  This field usually has a relocation
536225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 attached pointing to __gcc_personality_v0.  */
536325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      const unsigned char *startp = readp;
536425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      unsigned int encoding = *readp++;
536525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      uint64_t val = 0;
536625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      readp = read_encoded (encoding, readp,
536725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    readp - 1 + augmentationlen,
536825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &val, dbg);
536925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
537025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      while (++startp < readp)
537125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			printf ("%#x ", *startp);
537225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
537325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      putchar ('(');
537425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      print_encoding (encoding);
537525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      putchar (' ');
537625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      switch (encoding & 0xf)
537725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
537825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			case DW_EH_PE_sleb128:
537925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			case DW_EH_PE_sdata2:
538025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			case DW_EH_PE_sdata4:
538125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printf ("%" PRId64 ")\n", val);
538225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  break;
538325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			default:
538425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printf ("%#" PRIx64 ")\n", val);
538525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  break;
538625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
538725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
538825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
538925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf ("(%x)\n", *readp++);
539025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
539125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ++cp;
539225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
539325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
539425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
539525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (ptr_size == 4 || ptr_size == 8))
539625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
539725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct cieinfo *newp = alloca (sizeof (*newp));
539825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->cie_offset = offset;
539925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->augmentation = augmentation;
540025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->fde_encoding = fde_encoding;
540125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->lsda_encoding = lsda_encoding;
540225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->address_size = ptr_size;
540325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->code_alignment_factor = code_alignment_factor;
540425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->data_alignment_factor = data_alignment_factor;
540525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->next = cies;
540625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cies = newp;
540725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
540825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
540925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
541025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
541125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  struct cieinfo *cie = cies;
541225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (cie != NULL)
541325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (is_eh_frame
541425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? start - (ptrdiff_t) cie_id == cie->cie_offset
541525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: (ptrdiff_t) cie_id == cie->cie_offset)
541625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
541725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    else
541825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cie = cie->next;
541925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (cie == NULL))
542025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
542125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      puts ("invalid CIE reference in FDE");
542225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
542325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
542425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
542525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Initialize from CIE data.  */
542625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fde_encoding = cie->fde_encoding;
542725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  lsda_encoding = cie->lsda_encoding;
542825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
542925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  code_alignment_factor = cie->code_alignment_factor;
543025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data_alignment_factor = cie->data_alignment_factor;
543125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
543225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *base = readp;
543325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX There are sometimes relocations for this value
543425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  initial_location = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
543525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Word address_range
543625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
543725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
543825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *a = format_dwarf_addr (dwflmod, cie->address_size,
543925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       initial_location);
544025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
544125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   CIE_pointer:              %" PRIu64 "\n"
544225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   initial_location:         %s",
544325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  offset, (uint64_t) unit_length,
544425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  cie->cie_offset, (uint64_t) cie_id, a);
544525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (a);
544625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
544725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
544825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      vma_base = (((uint64_t) shdr->sh_offset
544925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   + (base - (const unsigned char *) data->d_buf)
545025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   + (uint64_t) initial_location)
545125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  & (ptr_size == 4
545225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     ? UINT64_C (0xffffffff)
545325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     : UINT64_C (0xffffffffffffffff)));
545425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (gettext (" (offset: %#" PRIx64 ")"),
545525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (uint64_t) vma_base);
545625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
545725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
545825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n   address_range:            %#" PRIx64,
545925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (uint64_t) address_range);
546025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
546125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" (end offset: %#" PRIx64 ")"),
546225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ((uint64_t) vma_base + (uint64_t) address_range)
546325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    & (ptr_size == 4
546425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       ? UINT64_C (0xffffffff)
546525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       : UINT64_C (0xffffffffffffffff)));
546625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar ('\n');
546725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
546825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (cie->augmentation[0] == 'z')
546925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
547025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int augmentationlen;
547125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      get_uleb128 (augmentationlen, readp);
547225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
547325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (augmentationlen > 0)
547425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
547525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  const char *hdr = "Augmentation data:";
547625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  const char *cp = cie->augmentation + 1;
547725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  unsigned int u = 0;
547825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (*cp != '\0')
547925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
548025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (*cp == 'L')
548125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
548225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  uint64_t lsda_pointer;
548325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  const unsigned char *p
548425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    = read_encoded (lsda_encoding, &readp[u],
548525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &readp[augmentationlen],
548625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &lsda_pointer, dbg);
548725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  u = p - readp;
548825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printf (gettext ("\
548925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   %-26sLSDA pointer: %#" PRIx64 "\n"),
549025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  hdr, lsda_pointer);
549125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  hdr = "";
549225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
549325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      ++cp;
549425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
549525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
549625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (u < augmentationlen)
549725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
549825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf ("   %-26s%#x\n", hdr, readp[u++]);
549925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      hdr = "";
550025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
550125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
550225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
550325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      readp += augmentationlen;
550425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
550525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
550625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
550725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the initialization instructions.  */
550825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
550925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 data_alignment_factor, version, ptr_size,
551025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 dwflmod, ebl, dbg);
551125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = cieend;
551225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
551325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
551425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
551525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
551625b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct attrcb_args
551725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
551825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwfl_Module *dwflmod;
551925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf *dbg;
552025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int level;
552125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool silent;
552225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int version;
552325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int addrsize;
552425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int offset_size;
552525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off cu_offset;
552625b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
552725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
552825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
552925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
553025b3c049e70834cf33790a28643ab058b507b35cBen Chengattr_callback (Dwarf_Attribute *attrp, void *arg)
553125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
553225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct attrcb_args *cbargs = (struct attrcb_args *) arg;
553325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const int level = cbargs->level;
553425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
553525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int attr = dwarf_whatattr (attrp);
553625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (attr == 0))
553725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
553825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!cbargs->silent)
553925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get attribute code: %s"),
554025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       dwarf_errmsg (-1));
554125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return DWARF_CB_ABORT;
554225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
554325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
554425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int form = dwarf_whatform (attrp);
554525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (form == 0))
554625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
554725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!cbargs->silent)
554825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get attribute form: %s"),
554925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       dwarf_errmsg (-1));
555025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return DWARF_CB_ABORT;
555125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
555225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
555325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (form)
555425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
555525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_addr:
555625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!cbargs->silent)
555725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
555825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Addr addr;
555925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
556025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
556125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    attrval_out:
556225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!cbargs->silent)
556325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		error (0, 0, gettext ("cannot get attribute value: %s"),
556425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       dwarf_errmsg (-1));
556525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return DWARF_CB_ABORT;
556625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
556725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
556825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("           %*s%-20s (%s) %s\n",
556925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (int) (level * 2), "", dwarf_attr_string (attr),
557025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  dwarf_form_string (form), a);
557125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (a);
557225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
557325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
557425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
557525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_indirect:
557625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_strp:
557725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_string:
557825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
557925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
558025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *str = dwarf_formstring (attrp);
558125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (str == NULL))
558225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
558325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) \"%s\"\n",
558425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) (level * 2), "", dwarf_attr_string (attr),
558525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      dwarf_form_string (form), str);
558625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
558725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
558825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref_addr:
558925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref_udata:
559025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref8:
559125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref4:
559225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref2:
559325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref1:;
559425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
559525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
559625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die ref;
559725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
559825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
559925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
560025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) [%6" PRIxMAX "]\n",
560125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) (level * 2), "", dwarf_attr_string (attr),
560225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      dwarf_form_string (form), (uintmax_t) dwarf_dieoffset (&ref));
560325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
560425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
560525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref_sig8:
560625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
560725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
560825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
560925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) (level * 2), "", dwarf_attr_string (attr),
561025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      dwarf_form_string (form),
561125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
561225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
561325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
561425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_sec_offset:
561525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_udata:
561625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_sdata:
561725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data8:
561825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data4:
561925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data2:
562025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data1:;
562125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word num;
562225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formudata (attrp, &num) != 0))
562325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
562425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
562525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *valuestr = NULL;
562625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (attr)
562725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
562825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This case can take either a constant or a loclistptr.  */
562925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_member_location:
563025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (form != DW_FORM_sec_offset
563125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (cbargs->version >= 4
563225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (form != DW_FORM_data4 && form != DW_FORM_data8)))
563325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
563425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!cbargs->silent)
563525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("           %*s%-20s (%s) %" PRIxMAX "\n",
563625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(int) (level * 2), "", dwarf_attr_string (attr),
563725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			dwarf_form_string (form), (uintmax_t) num);
563825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return DWARF_CB_OK;
563925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
564025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* else fallthrough */
564125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
564225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* These cases always take a loclistptr and no constant. */
564325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_location:
564425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_location:
564525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_vtable_elem_location:
564625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_string_length:
564725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_use_location:
564825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_frame_base:
564925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_return_addr:
565025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_static_link:
565125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_value:
565225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_data_value:
565325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target:
565425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target_clobbered:
565525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  notice_listptr (section_loc, &known_loclistptr,
565625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  cbargs->addrsize, cbargs->offset_size, num);
565725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!cbargs->silent)
565825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
565925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    (int) (level * 2), "", dwarf_attr_string (attr),
566025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    dwarf_form_string (form), (uintmax_t) num);
566125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return DWARF_CB_OK;
566225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
566325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_ranges:
566425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  notice_listptr (section_ranges, &known_rangelistptr,
566525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  cbargs->addrsize, cbargs->offset_size, num);
566625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!cbargs->silent)
566725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("           %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
566825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    (int) (level * 2), "", dwarf_attr_string (attr),
566925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    dwarf_form_string (form), (uintmax_t) num);
567025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return DWARF_CB_OK;
567125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
567225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_language:
567325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_lang_string (num);
567425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
567525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_encoding:
567625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_encoding_string (num);
567725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
567825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_accessibility:
567925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_access_string (num);
568025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
568125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_visibility:
568225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_visibility_string (num);
568325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
568425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_virtuality:
568525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_virtuality_string (num);
568625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
568725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_identifier_case:
568825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_identifier_case_string (num);
568925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
569025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_calling_convention:
569125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_calling_convention_string (num);
569225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
569325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_inline:
569425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_inline_string (num);
569525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
569625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_ordering:
569725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_ordering_string (num);
569825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
569925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_discr_list:
570025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  valuestr = dwarf_discr_list_string (num);
570125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
570225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
570325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Nothing.  */
570425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
570525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
570625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
570725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
570825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
570925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
571025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (valuestr == NULL)
571125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
571225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(int) (level * 2), "", dwarf_attr_string (attr),
571325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		dwarf_form_string (form), (uintmax_t) num);
571425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
571525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("           %*s%-20s (%s) %s (%" PRIuMAX ")\n",
571625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(int) (level * 2), "", dwarf_attr_string (attr),
571725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		dwarf_form_string (form), valuestr, (uintmax_t) num);
571825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
571925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
572025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_flag:
572125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
572225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
572325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool flag;
572425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formflag (attrp, &flag) != 0))
572525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
572625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
572725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) %s\n",
572825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) (level * 2), "", dwarf_attr_string (attr),
572925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      dwarf_form_string (form), nl_langinfo (flag ? YESSTR : NOSTR));
573025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
573125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
573225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_flag_present:
573325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
573425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
573525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) %s\n",
573625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) (level * 2), "", dwarf_attr_string (attr),
573725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      dwarf_form_string (form), nl_langinfo (YESSTR));
573825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
573925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
574025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_exprloc:
574125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block4:
574225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block2:
574325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block1:
574425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block:
574525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
574625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
574725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Block block;
574825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formblock (attrp, &block) != 0))
574925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
575025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
575125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) ",
575225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) (level * 2), "", dwarf_attr_string (attr),
575325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      dwarf_form_string (form));
575425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
575525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (attr)
575625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
575725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
575825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (form != DW_FORM_exprloc)
575925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
576025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      print_block (block.length, block.data);
576125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
576225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
576325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Fall through.  */
576425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
576525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_location:
576625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_location:
576725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_member_location:
576825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_vtable_elem_location:
576925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_string_length:
577025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_use_location:
577125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_frame_base:
577225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_return_addr:
577325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_static_link:
577425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_allocated:
577525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_associated:
577625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_bit_size:
577725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_bit_offset:
577825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_bit_stride:
577925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_byte_size:
578025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_byte_stride:
578125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_count:
578225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_lower_bound:
578325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_upper_bound:
578425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_value:
578525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_data_value:
578625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target:
578725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target_clobbered:
578825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar ('\n');
578925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_ops (cbargs->dwflmod, cbargs->dbg,
579025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     12 + level * 2, 12 + level * 2,
579125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     cbargs->version, cbargs->addrsize, cbargs->offset_size,
579225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     block.length, block.data);
579325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
579425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
579525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
579625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
579725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
579825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
579925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
580025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (form: %#x) ???\n",
580125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) (level * 2), "", dwarf_attr_string (attr),
580225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) form);
580325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
580425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
580525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
580625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return DWARF_CB_OK;
580725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
580825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
580925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
581025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_units (Dwfl_Module *dwflmod,
581125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Ebl *ebl, GElf_Ehdr *ehdr,
581225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Elf_Scn *scn, GElf_Shdr *shdr,
581325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Dwarf *dbg, bool debug_types)
581425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
581525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const bool silent = !(print_debug_sections & section_info);
581625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *secname = section_name (ebl, ehdr, shdr);
581725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
581825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!silent)
581925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
582025b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
582125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
582225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
582325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If the section is empty we don't have to do anything.  */
582425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!silent && shdr->sh_size == 0)
582525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
582625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
582725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int maxdies = 20;
582825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
582925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
583025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset = 0;
583125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
583225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* New compilation unit.  */
583325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cuhl;
583425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Half version;
583525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off abbroffset;
583625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint8_t addrsize;
583725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint8_t offsize;
583825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off nextcu;
583925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint64_t typesig;
584025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off typeoff;
584125b3c049e70834cf33790a28643ab058b507b35cBen Cheng next_cu:
584225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
584325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       &abbroffset, &addrsize, &offsize,
584425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       debug_types ? &typesig : NULL,
584525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       debug_types ? &typeoff : NULL) != 0)
584625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto do_return;
584725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
584825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!silent)
584925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
585025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (debug_types)
585125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" Type unit at offset %" PRIu64 ":\n"
585225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 " Version: %" PRIu16 ", Abbreviation section offset: %"
585325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 PRIu64 ", Address size: %" PRIu8
585425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", Offset size: %" PRIu8
585525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 "\n Type signature: %#" PRIx64
585625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", Type offset: %#" PRIx64 "\n"),
585725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) offset, version, abbroffset, addrsize, offsize,
585825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		typesig, (uint64_t) typeoff);
585925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
586025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
586125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 " Version: %" PRIu16 ", Abbreviation section offset: %"
586225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 PRIu64 ", Address size: %" PRIu8
586325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", Offset size: %" PRIu8 "\n"),
586425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) offset, version, abbroffset, addrsize, offsize);
586525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
586625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
586725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct attrcb_args args =
586825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
586925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .dwflmod = dwflmod,
587025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .dbg = dbg,
587125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .silent = silent,
587225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .version = version,
587325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .addrsize = addrsize,
587425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .offset_size = offsize,
587525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .cu_offset = offset
587625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
587725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
587825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  offset += cuhl;
587925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
588025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int level = 0;
588125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
588225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
588325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(dbg, offset, &dies[level]) == NULL))
588425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
588525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!silent)
588625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
588725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      " in section '%s': %s"),
588825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       (uint64_t) offset, secname, dwarf_errmsg (-1));
588925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto do_return;
589025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
589125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
589225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
589325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
589425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset = dwarf_dieoffset (&dies[level]);
589525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (offset == ~0ul))
589625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
589725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!silent)
589825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("cannot get DIE offset: %s"),
589925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   dwarf_errmsg (-1));
590025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto do_return;
590125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
590225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
590325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int tag = dwarf_tag (&dies[level]);
590425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (tag == DW_TAG_invalid))
590525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
590625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!silent)
590725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
590825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  " in section '%s': %s"),
590925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   (uint64_t) offset, secname, dwarf_errmsg (-1));
591025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto do_return;
591125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
591225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
591325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!silent)
591425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (" [%6" PRIx64 "]  %*s%s\n",
591525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) offset, (int) (level * 2), "",
591625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		dwarf_tag_string (tag));
591725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
591825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Print the attribute values.  */
591925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      args.level = level;
592025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
592125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
592225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Make room for the next level's DIE.  */
592325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (level + 1 == maxdies)
592425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	dies = (Dwarf_Die *) xrealloc (dies,
592525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       (maxdies += 10)
592625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       * sizeof (Dwarf_Die));
592725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
592825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int res = dwarf_child (&dies[level], &dies[level + 1]);
592925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (res > 0)
593025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
593125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
593225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (level-- == 0)
593325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
593425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
593525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (res == -1))
593625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
593725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!silent)
593825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		error (0, 0, gettext ("cannot get next DIE: %s\n"),
593925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       dwarf_errmsg (-1));
594025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      goto do_return;
594125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
594225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
594325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (unlikely (res < 0))
594425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
594525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!silent)
594625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("cannot get next DIE: %s"),
594725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   dwarf_errmsg (-1));
594825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto do_return;
594925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
595025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
595125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	++level;
595225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
595325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (level >= 0);
595425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
595525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  offset = nextcu;
595625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (offset != 0)
595725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     goto next_cu;
595825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
595925b3c049e70834cf33790a28643ab058b507b35cBen Cheng do_return:
596025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (dies);
596125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
596225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
596325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
596425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
596525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
596625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
596725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
596825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
596925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
597025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
597125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
597225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
597325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
597425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
597525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
597625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
597725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
597825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
597925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
598025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
598125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
598225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
598325b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
598425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
598525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
598625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
598725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_size == 0)
598825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
598925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
599025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* There is no functionality in libdw to read the information in the
599125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     way it is represented here.  Hardcode the decoder.  */
599225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
599325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL || data->d_buf == NULL))
599425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
599525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get line data section data: %s"),
599625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
599725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
599825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
599925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
600025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *linep = (const unsigned char *) data->d_buf;
600125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *lineendp;
600225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
600325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (linep
600425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
600525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
600625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t start_offset = linep - (const unsigned char *) data->d_buf;
600725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
600825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
600925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
601025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
601125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int length = 4;
601225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (unit_length == 0xffffffff))
601325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
601425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (linep + 8 > lineendp))
601525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
601625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    invalid_data:
601725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
601825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
601925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
602025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
602125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
602225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  length = 8;
602325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
602425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
602525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Check whether we have enough room in the section.  */
602625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unit_length < 2 + length + 5 * 1
602725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || unlikely (linep + unit_length > lineendp))
602825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
602925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      lineendp = linep + unit_length;
603025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
603125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The next element of the header is the version identifier.  */
603225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
603325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
603425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Next comes the header length.  */
603525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word header_length;
603625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (length == 4)
603725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	header_length = read_4ubyte_unaligned_inc (dbg, linep);
603825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
603925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	header_length = read_8ubyte_unaligned_inc (dbg, linep);
604025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      //const unsigned char *header_start = linep;
604125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
604225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Next the minimum instruction length.  */
604325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t minimum_instr_len = *linep++;
604425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
604525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Next the maximum operations per instruction, in version 4 format.  */
604625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
604725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
604825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Then the flag determining the default value of the is_stmt
604925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   register.  */
605025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t default_is_stmt = *linep++;
605125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
605225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Now the line base.  */
605325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int_fast8_t line_base = *((const int_fast8_t *) linep);
605425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++linep;
605525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
605625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* And the line range.  */
605725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t line_range = *linep++;
605825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
605925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The opcode base.  */
606025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t opcode_base = *linep++;
606125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
606225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Print what we got so far.  */
606325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\n"
606425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Length:                     %" PRIu64 "\n"
606525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " DWARF version:              %" PRIuFAST16 "\n"
606625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Prologue length:            %" PRIu64 "\n"
606725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Minimum instruction length: %" PRIuFAST8 "\n"
606825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Maximum operations per instruction: %" PRIuFAST8 "\n"
606925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Initial value if '%s': %" PRIuFAST8 "\n"
607025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Line base:                  %" PRIdFAST8 "\n"
607125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Line range:                 %" PRIuFAST8 "\n"
607225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Opcode base:                %" PRIuFAST8 "\n"
607325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "\n"
607425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "Opcodes:\n"),
607525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (uint64_t) unit_length, version, (uint64_t) header_length,
607625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      minimum_instr_len, max_ops_per_instr,
607725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      "is_stmt", default_is_stmt, line_base,
607825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      line_range, opcode_base);
607925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
608025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (linep + opcode_base - 1 >= lineendp))
608125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
608225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	invalid_unit:
608325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0,
608425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
608525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 linep - (const unsigned char *) data->d_buf,
608625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
608725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  linep = lineendp;
608825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
608925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
609025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int opcode_base_l10 = 1;
609125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int tmp = opcode_base;
609225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (tmp > 10)
609325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
609425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  tmp /= 10;
609525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++opcode_base_l10;
609625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
609725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const uint8_t *standard_opcode_lengths = linep - 1;
609825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
609925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
610025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
610125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (int) linep[cnt - 1]),
610225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		opcode_base_l10, cnt, linep[cnt - 1]);
610325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      linep += opcode_base - 1;
610425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (linep >= lineendp))
610525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_unit;
610625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
610725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext ("\nDirectory table:"));
610825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (*linep != 0)
610925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
611025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
611125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (endp == NULL))
611225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_unit;
611325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
611425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" %s\n", (char *) linep);
611525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
611625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  linep = endp + 1;
611725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
611825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Skip the final NUL byte.  */
611925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++linep;
612025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
612125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (linep >= lineendp))
612225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_unit;
612325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext ("\nFile name table:\n"
612425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     " Entry Dir   Time      Size      Name"));
612525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (unsigned int cnt = 1; *linep != 0; ++cnt)
612625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
612725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* First comes the file name.  */
612825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *fname = (char *) linep;
612925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
613025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (endp == NULL))
613125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_unit;
613225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  linep = endp + 1;
613325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
613425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Then the index.  */
613525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int diridx;
613625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (diridx, linep);
613725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
613825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Next comes the modification time.  */
613925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int mtime;
614025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (mtime, linep);
614125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
614225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Finally the length of the file.  */
614325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int fsize;
614425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (fsize, linep);
614525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
614625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" %-5u %-5u %-9u %-9u %s\n",
614725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  cnt, diridx, mtime, fsize, fname);
614825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
614925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Skip the final NUL byte.  */
615025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++linep;
615125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
615225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext ("\nLine number statements:"));
615325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word address = 0;
615425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int op_index = 0;
615525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t line = 1;
615625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t is_stmt = default_is_stmt;
615725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
615825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Default address value, in case we do not find the CU.  */
615925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t address_size
616025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
616125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
616225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Determine the CU this block is for.  */
616325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off cuoffset;
616425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off ncuoffset = 0;
616525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t hsize;
616625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
616725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   NULL, NULL, NULL) == 0)
616825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
616925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Die cudie;
617025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
617125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
617225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Attribute stmt_list;
617325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
617425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
617525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Word lineoff;
617625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
617725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
617825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (lineoff == start_offset)
617925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
618025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Found the CU.  */
618125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      address_size = cudie.cu->address_size;
618225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
618325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
618425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
618525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
618625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Apply the "operation advance" from a special opcode
618725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
618825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int op_addr_advance;
618925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool show_op_index;
619025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      inline void advance_pc (unsigned int op_advance)
619125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
619225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	op_addr_advance = minimum_instr_len * ((op_index + op_advance)
619325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       / max_ops_per_instr);
619425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	address += op_advance;
619525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	show_op_index = (op_index > 0 ||
619625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (op_index + op_advance) % max_ops_per_instr > 0);
619725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	op_index = (op_index + op_advance) % max_ops_per_instr;
619825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
619925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
620025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (linep < lineendp)
620125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
620225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t offset = linep - (const unsigned char *) data->d_buf;
620325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int u128;
620425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int s128;
620525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
620625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Read the opcode.  */
620725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int opcode = *linep++;
620825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
620925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%6" PRIx64 "]", (uint64_t)offset);
621025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Is this a special opcode?  */
621125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (opcode >= opcode_base))
621225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
621325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Yes.  Handling this is quite easy since the opcode value
621425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 is computed with
621525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
621625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 opcode = (desired line increment - line_base)
621725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   + (line_range * address advance) + opcode_base
621825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      */
621925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int line_increment = (line_base
622025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    + (opcode - opcode_base) % line_range);
622125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
622225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Perform the increments.  */
622325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      line += line_increment;
622425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      advance_pc ((opcode - opcode_base) / line_range);
622525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
622625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      char *a = format_dwarf_addr (dwflmod, 0, address);
622725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (show_op_index)
622825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf (gettext ("\
622925b3c049e70834cf33790a28643ab058b507b35cBen Cheng special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
623025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			opcode, op_addr_advance, a, op_index,
623125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			line_increment, line);
623225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
623325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf (gettext ("\
623425b3c049e70834cf33790a28643ab058b507b35cBen Cheng special opcode %u: address+%u = %s, line%+d = %zu\n"),
623525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			opcode, op_addr_advance, a, line_increment, line);
623625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      free (a);
623725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
623825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (opcode == 0)
623925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
624025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This an extended opcode.  */
624125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (linep + 2 > lineendp))
624225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto invalid_unit;
624325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
624425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The length.  */
624525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int len = *linep++;
624625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
624725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (linep + len > lineendp))
624825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto invalid_unit;
624925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The sub-opcode.  */
625125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      opcode = *linep++;
625225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (gettext (" extended opcode %u: "), opcode);
625425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      switch (opcode)
625625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
625725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_end_sequence:
625825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" end of sequence"));
625925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
626025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Reset the registers we care about.  */
626125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  address = 0;
626225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  op_index = 0;
626325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  line = 1;
626425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_stmt = default_is_stmt;
626525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
626625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
626725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_set_address:
626825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  op_index = 0;
626925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (address_size == 4)
627025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    address = read_4ubyte_unaligned_inc (dbg, linep);
627125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
627225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    address = read_8ubyte_unaligned_inc (dbg, linep);
627325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
627425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
627525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext (" set address to %s\n"), a);
627625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
627725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
627825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
627925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
628025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_define_file:
628125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
628225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    char *fname = (char *) linep;
628325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    unsigned char *endp = memchr (linep, '\0',
628425b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  lineendp - linep);
628525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (unlikely (endp == NULL))
628625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      goto invalid_unit;
628725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    linep = endp + 1;
628825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
628925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    unsigned int diridx;
629025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    get_uleb128 (diridx, linep);
629125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    Dwarf_Word mtime;
629225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    get_uleb128 (mtime, linep);
629325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    Dwarf_Word filelength;
629425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    get_uleb128 (filelength, linep);
629525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
629625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("\
629725b3c049e70834cf33790a28643ab058b507b35cBen Cheng define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
629825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    diridx, (uint64_t) mtime, (uint64_t) filelength,
629925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    fname);
630025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
630125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
630225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
630325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_set_discriminator:
630425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one ULEB128 parameter, the discriminator.  */
630525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
630625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
630725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
630825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_uleb128 (u128, linep);
630925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set discriminator to %u\n"), u128);
631025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
631125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
631225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		default:
631325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Unknown, ignore it.  */
631425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" unknown opcode"));
631525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  linep += len - 1;
631625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
631725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
631825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
631925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (opcode <= DW_LNS_set_isa)
632025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
632125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is a known standard opcode.  */
632225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      switch (opcode)
632325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
632425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_copy:
632525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
632625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" copy"));
632725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
632825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
632925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_advance_pc:
633025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is added to the
633125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     address.  */
633225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_uleb128 (u128, linep);
633325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  advance_pc (u128);
633425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
633525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
633625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (show_op_index)
633725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext ("\
633825b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by %u to %s, op_index to %u\n"),
633925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a, op_index);
634025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else
634125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext (" advance address by %u to %s\n"),
634225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a);
634325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
634425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
634525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
634625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
634725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_advance_line:
634825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one sleb128 parameter which is added to the
634925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     line.  */
635025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_sleb128 (s128, linep);
635125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  line += s128;
635225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext ("\
635325b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance line by constant %d to %" PRId64 "\n"),
635425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  s128, (int64_t) line);
635525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
635625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
635725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_file:
635825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is stored in file.  */
635925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_uleb128 (u128, linep);
636025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set file to %" PRIu64 "\n"),
636125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (uint64_t) u128);
636225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
636325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
636425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_column:
636525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is stored in column.  */
636625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
636725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
636825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
636925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_uleb128 (u128, linep);
637025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set column to %" PRIu64 "\n"),
637125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (uint64_t) u128);
637225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
637325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
637425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_negate_stmt:
637525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
637625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_stmt = 1 - is_stmt;
637725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
637825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  "is_stmt", is_stmt);
637925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
638025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
638125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_basic_block:
638225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
638325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" set basic block flag"));
638425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
638525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
638625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_const_add_pc:
638725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
638825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  advance_pc ((255 - opcode_base) / line_range);
638925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
639025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
639125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (show_op_index)
639225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext ("\
639325b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by constant %u to %s, op_index to %u\n"),
639425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a, op_index);
639525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else
639625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext ("\
639725b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by constant %u to %s\n"),
639825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a);
639925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
640025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
640125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
640225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
640325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_fixed_advance_pc:
640425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one 16 bit parameter which is added to the
640525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     address.  */
640625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
640725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
640825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
640925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
641025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  address += u128;
641125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  op_index = 0;
641225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
641325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
641425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("\
641525b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by fixed value %u to %s\n"),
641625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    u128, a);
641725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
641825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
641925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
642025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
642125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_prologue_end:
642225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
642325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" set prologue end flag"));
642425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
642525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
642625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_epilogue_begin:
642725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
642825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" set epilogue begin flag"));
642925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
643025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
643125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_isa:
643225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is stored in isa.  */
643325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
643425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
643525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
643625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_uleb128 (u128, linep);
643725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set isa to %u\n"), u128);
643825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
643925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
644025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
644125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
644225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
644325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is a new opcode the generator but not we know about.
644425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 Read the parameters associated with it but then discard
644525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 everything.  Read all the parameters for this opcode.  */
644625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
644725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				" unknown opcode with %" PRIu8 " parameters:",
644825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				standard_opcode_lengths[opcode]),
644925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      standard_opcode_lengths[opcode]);
645025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
645125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
645225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_uleb128 (u128, linep);
645325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (n != standard_opcode_lengths[opcode])
645425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    putc_unlocked (',', stdout);
645525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (" %u", u128);
645625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
645725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
645825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Next round, ignore this opcode.  */
645925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
646025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
646125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
646225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
646325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
646425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* There must only be one data block.  */
646525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (elf_getdata (scn, data) == NULL);
646625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
646725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
646825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
646925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
647025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_loc_section (Dwfl_Module *dwflmod,
647125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Ebl *ebl, GElf_Ehdr *ehdr,
647225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
647325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
647425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
647525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
647625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
647725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
647825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get .debug_loc content: %s"),
647925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
648025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
648125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
648225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
648325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
648425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
648525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
648625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
648725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
648825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sort_listptr (&known_loclistptr, "loclistptr");
648925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t listptr_idx = 0;
649025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
649125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
649225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t offset_size = 4;
649325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
649425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool first = true;
649525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *readp = data->d_buf;
649625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
649725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < endp)
649825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
649925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
650025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
650125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
650225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &address_size, &offset_size,
650325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      offset, &readp, endp))
650425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
650525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
650625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (data->d_size - offset < address_size * 2))
650725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
650825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
650925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
651025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
651125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
651225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr begin;
651325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr end;
651425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (address_size == 8)
651525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
651625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_8ubyte_unaligned_inc (dbg, readp);
651725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_8ubyte_unaligned_inc (dbg, readp);
651825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
651925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
652025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
652125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_4ubyte_unaligned_inc (dbg, readp);
652225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_4ubyte_unaligned_inc (dbg, readp);
652325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (begin == (Dwarf_Addr) (uint32_t) -1)
652425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    begin = (Dwarf_Addr) -1l;
652525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
652625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
652725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
652825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
652925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, end);
653025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
653125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
653225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
653325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (begin == 0 && end == 0) /* End of list entry.  */
653425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
653525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)
653625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  empty list\n"), offset);
653725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = true;
653825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
653925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
654025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
654125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We have a location expression entry.  */
654225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
654325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
654425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
654525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *e = format_dwarf_addr (dwflmod, address_size, end);
654625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
654725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)		/* First entry in a list.  */
654825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
654925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
655025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext ("           %s..%s"), b, e);
655125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
655225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
655325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (e);
655425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
655525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (endp - readp <= (ptrdiff_t) len)
655625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
655725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      fputs (gettext ("   <INVALID DATA>\n"), stdout);
655825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
655925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
656025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
656125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
656225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     3 /*XXX*/, address_size, offset_size, len, readp);
656325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
656425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = false;
656525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp += len;
656625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
656725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
656825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
656925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
657025b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct mac_culist
657125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
657225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Die die;
657325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset;
657425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Files *files;
657525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *next;
657625b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
657725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
657825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
657925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
658025b3c049e70834cf33790a28643ab058b507b35cBen Chengmac_compare (const void *p1, const void *p2)
658125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
658225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *m1 = (struct mac_culist *) p1;
658325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *m2 = (struct mac_culist *) p2;
658425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
658525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (m1->offset < m2->offset)
658625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
658725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (m1->offset > m2->offset)
658825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
658925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
659025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
659125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
659225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
659325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
659425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
659525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Ebl *ebl, GElf_Ehdr *ehdr,
659625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
659725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
659825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
659925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
660025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
660125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
660225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  putc_unlocked ('\n', stdout);
660325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
660425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* There is no function in libdw to iterate over the raw content of
660525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     the section but it is easy enough to do.  */
660625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
660725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL || data->d_buf == NULL))
660825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
660925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get macro information section data: %s"),
661025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
661125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
661225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
661325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
661425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the source file information for all CUs.  */
661525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset;
661625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off ncu = 0;
661725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t hsize;
661825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *culist = NULL;
661925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nculist = 0;
662025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
662125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
662225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die cudie;
662325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
662425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
662525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
662625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Attribute attr;
662725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
662825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
662925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
663025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word macoff;
663125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_formudata (&attr, &macoff) != 0)
663225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
663325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
663425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
663525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->die = cudie;
663625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->offset = macoff;
663725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->files = NULL;
663825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->next = culist;
663925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      culist = newp;
664025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++nculist;
664125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
664225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
664325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Convert the list into an array for easier consumption.  */
664425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
664525b3c049e70834cf33790a28643ab058b507b35cBen Cheng							 * sizeof (*cus));
664625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Add sentinel.  */
664725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  cus[nculist].offset = data->d_size;
664825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nculist > 0)
664925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
665025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t cnt = nculist - 1; culist != NULL; --cnt)
665125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
665225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (cnt < nculist);
665325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cus[cnt] = *culist;
665425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  culist = culist->next;
665525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
665625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
665725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Sort the array according to the offset in the .debug_macinfo
665825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 section.  Note we keep the sentinel at the end.  */
665925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      qsort (cus, nculist, sizeof (*cus), mac_compare);
666025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
666125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
666225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = (const unsigned char *) data->d_buf;
666325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readendp = readp + data->d_size;
666425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int level = 1;
666525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
666625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < readendp)
666725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
666825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int opcode = *readp++;
666925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int u128;
667025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int u128_2;
667125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *endp;
667225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
667325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (opcode)
667425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
667525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_define:
667625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_undef:
667725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_vendor_ext:
667825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /*  For the first two opcodes the parameters are
667925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		line, string
668025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      For the latter
668125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		number, string.
668225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      We can treat these cases together.  */
668325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (u128, readp);
668425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
668525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  endp = memchr (readp, '\0', readendp - readp);
668625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (endp == NULL))
668725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
668825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (gettext ("\
668925b3c049e70834cf33790a28643ab058b507b35cBen Cheng%*s*** non-terminated string at end of section"),
669025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      level, "");
669125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
669225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
669325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
669425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (opcode == DW_MACINFO_define)
669525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s#define %s, line %u\n",
669625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    level, "", (char *) readp, u128);
669725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (opcode == DW_MACINFO_undef)
669825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s#undef %s, line %u\n",
669925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    level, "", (char *) readp, u128);
670025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
670125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
670225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
670325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = endp + 1;
670425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
670525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
670625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_start_file:
670725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The two parameters are line and file index, in this order.  */
670825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (u128, readp);
670925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_uleb128 (u128_2, readp);
671025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
671125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Find the CU DIE for this file.  */
671225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t macoff = readp - (const unsigned char *) data->d_buf;
671325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *fname = "???";
671425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (macoff >= cus[0].offset)
671525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
671625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      while (macoff >= cus[1].offset)
671725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		++cus;
671825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
671925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (cus[0].files == NULL
672025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
672125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		cus[0].files = (Dwarf_Files *) -1l;
672225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
672325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (cus[0].files != (Dwarf_Files *) -1l)
672425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
672525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ?: "???");
672625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
672725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
672825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*sstart_file %u, [%u] %s\n",
672925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  level, "", u128, u128_2, fname);
673025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++level;
673125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
673225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
673325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_end_file:
673425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  --level;
673525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*send_file\n", level, "");
673625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Nothing more to do.  */
673725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
673825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
673925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
674025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX gcc seems to generate files with a trailing zero.
674125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (opcode != 0 || readp != readendp))
674225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
674325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
674425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
674525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
674625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
674725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
674825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
674925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Callback for printing global names.  */
675025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
675125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
675225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		void *arg)
675325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
675425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int *np = (int *) arg;
675525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
675625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" [%5d] DIE offset: %6" PRId64
675725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
675825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (*np)++, global->die_offset, global->cu_offset, global->name);
675925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
676025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
676125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
676225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
676325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
676425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
676525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
676625b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
676725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      Ebl *ebl, GElf_Ehdr *ehdr,
676825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
676925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
677025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
677125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
677225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
677325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
677425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int n = 0;
677525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
677625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
677725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
677825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the DWARF string section '.debug_str'.  */
677925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
678025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
678125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Ebl *ebl, GElf_Ehdr *ehdr,
678225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
678325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
678425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size;
678525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
678625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Compute floor(log16(shdr->sh_size)).  */
678725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr tmp = sh_size;
678825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int digits = 1;
678925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (tmp >= 16)
679025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
679125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++digits;
679225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      tmp >>= 4;
679325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
679425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  digits = MAX (4, digits);
679525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
679625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
679725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " %*s  String\n"),
679825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn),
679925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
680025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* TRANS: the debugstr| prefix makes the string unique.  */
680125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  digits + 2, sgettext ("debugstr|Offset"));
680225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
680325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset = 0;
680425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (offset < sh_size)
680525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
680625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t len;
680725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *str = dwarf_getstring (dbg, offset, &len);
680825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (str == NULL))
680925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
681025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" *** error while reading strings: %s\n"),
681125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  dwarf_errmsg (-1));
681225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
681325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
681425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
681525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
681625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
681725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += len + 1;
681825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
681925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
682025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
682125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
682225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the call frame search table section
682325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   '.eh_frame_hdr'.  */
682425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
682525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
682625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       Ebl *ebl __attribute__ ((unused)),
682725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       GElf_Ehdr *ehdr __attribute__ ((unused)),
682825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
682925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
683025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
683125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
683225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn));
683325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
683425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
683525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
683625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
683725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
683825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
683925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ".eh_frame_hdr", elf_errmsg (-1));
684025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
684125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
684225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
684325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
684425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = ((unsigned char *) data->d_buf
684525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					+ data->d_size);
684625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
684725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
684825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
684925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid_data:
685025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("invalid data"));
685125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
685225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
685325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
685425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int version = *readp++;
685525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int eh_frame_ptr_enc = *readp++;
685625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int fde_count_enc = *readp++;
685725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int table_enc = *readp++;
685825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
685925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (" version:          %u\n"
686025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  " eh_frame_ptr_enc: %#x ",
686125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  version, eh_frame_ptr_enc);
686225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", eh_frame_ptr_enc);
686325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (" fde_count_enc:    %#x ", fde_count_enc);
686425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", fde_count_enc);
686525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (" table_enc:        %#x ", table_enc);
686625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", table_enc);
686725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
686825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint64_t eh_frame_ptr = 0;
686925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (eh_frame_ptr_enc != DW_EH_PE_omit)
687025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
687125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
687225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    dbg);
687325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (readp == NULL))
687425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
687525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
687625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
687725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
687825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (" (offset: %#" PRIx64 ")",
687925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* +4 because of the 4 byte header of the section.  */
688025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
688125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
688225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar_unlocked ('\n');
688325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
688425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
688525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint64_t fde_count = 0;
688625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fde_count_enc != DW_EH_PE_omit)
688725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
688825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
688925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (readp == NULL))
689025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
689125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
689225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" fde_count:        %" PRIu64 "\n", fde_count);
689325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
689425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
689525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fde_count == 0 || table_enc == DW_EH_PE_omit)
689625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
689725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
689825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (" Table:");
689925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
690025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Optimize for the most common case.  */
690125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
690225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (fde_count > 0 && readp + 8 <= dataend)
690325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
690425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
690525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	uint64_t initial_offset = ((uint64_t) shdr->sh_offset
690625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   + (int64_t) initial_location);
690725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
690825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	// XXX Possibly print symbol name or section offset for initial_offset
690925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
691025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		" fde=[%6" PRIx64 "]\n",
691125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		initial_location, initial_offset,
691225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		address, address - (eh_frame_ptr + 4));
691325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
691425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
691525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (0 && readp < dataend)
691625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
691725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
691825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
691925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
692025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
692125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
692225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the exception handling table section
692325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   '.eh_frame_hdr'.  */
692425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
692525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
692625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Ebl *ebl __attribute__ ((unused)),
692725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     GElf_Ehdr *ehdr __attribute__ ((unused)),
692825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Elf_Scn *scn,
692925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     GElf_Shdr *shdr __attribute__ ((unused)),
693025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Dwarf *dbg __attribute__ ((unused)))
693125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
693225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
693325b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nException handling table section [%2zu] '.gcc_except_table':\n"),
693425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn));
693525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
693625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
693725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
693825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
693925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
694025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
694125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ".gcc_except_table", elf_errmsg (-1));
694225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
694325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
694425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
694525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
694625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = readp + data->d_size;
694725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
694825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 1 > dataend))
694925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
695025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid_data:
695125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("invalid data"));
695225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
695325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
695425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int lpstart_encoding = *readp++;
695525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
695625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", lpstart_encoding);
695725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (lpstart_encoding != DW_EH_PE_omit)
695825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
695925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t lpstart;
696025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
696125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" LPStart:             %#" PRIx64 "\n", lpstart);
696225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
696325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
696425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 1 > dataend))
696525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
696625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int ttype_encoding = *readp++;
696725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" TType encoding:      %#x "), ttype_encoding);
696825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", ttype_encoding);
696925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *ttype_base = NULL;
697025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ttype_encoding != DW_EH_PE_omit)
697125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
697225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int ttype_base_offset;
697325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      get_uleb128 (ttype_base_offset, readp);
697425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" TType base offset:   %#x\n", ttype_base_offset);
697525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ttype_base = readp + ttype_base_offset;
697625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
697725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
697825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 1 > dataend))
697925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
698025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int call_site_encoding = *readp++;
698125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
698225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", call_site_encoding);
698325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int call_site_table_len;
698425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  get_uleb128 (call_site_table_len, readp);
698525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
698625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const action_table = readp + call_site_table_len;
698725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (action_table > dataend))
698825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
698925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int u = 0;
699025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int max_action = 0;
699125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < action_table)
699225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
699325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (u == 0)
699425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	puts (gettext ("\n Call site table:"));
699525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
699625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t call_site_start;
699725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (call_site_encoding, readp, dataend,
699825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    &call_site_start, dbg);
699925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t call_site_length;
700025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (call_site_encoding, readp, dataend,
700125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    &call_site_length, dbg);
700225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t landing_pad;
700325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (call_site_encoding, readp, dataend,
700425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    &landing_pad, dbg);
700525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int action;
700625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      get_uleb128 (action, readp);
700725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      max_action = MAX (action, max_action);
700825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
700925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "        Call site length:  %" PRIu64 "\n"
701025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "        Landing pad:       %#" PRIx64 "\n"
701125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "        Action:            %u\n"),
701225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      u++, call_site_start, call_site_length, landing_pad, action);
701325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
701425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (readp == action_table);
701525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
701625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int max_ar_filter = 0;
701725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (max_action > 0)
701825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
701925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts ("\n Action table:");
702025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
702125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *const action_table_end
702225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	= action_table + max_action + 1;
702325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
702425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      u = 0;
702525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
702625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
702725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int ar_filter;
702825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (ar_filter, readp);
702925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
703025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    max_ar_filter = ar_filter;
703125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int ar_disp;
703225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  get_sleb128 (ar_disp, readp);
703325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
703425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%4u] ar_filter:  % d\n"
703525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "        ar_disp:    % -5d",
703625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  u, ar_filter, ar_disp);
703725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (abs (ar_disp) & 1)
703825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
703925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (ar_disp != 0)
704025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts (" -> ???");
704125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
704225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    putchar_unlocked ('\n');
704325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++u;
704425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
704525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (readp < action_table_end);
704625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
704725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
704825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (max_ar_filter > 0)
704925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
705025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts ("\n TType table:");
705125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
705225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      // XXX Not *4, size of encoding;
705325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (ttype_encoding & 7)
705425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
705525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_udata2:
705625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_sdata2:
705725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = ttype_base - max_ar_filter * 2;
705825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
705925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_udata4:
706025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_sdata4:
706125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = ttype_base - max_ar_filter * 4;
706225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
706325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_udata8:
706425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_sdata8:
706525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = ttype_base - max_ar_filter * 8;
706625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
706725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
706825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (1, 0, gettext ("invalid TType encoding"));
706925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
707025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
707125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
707225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
707325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t ttype;
707425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
707525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				dbg);
707625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
707725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
707825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (readp < ttype_base);
707925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
708025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
708125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
708225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the '.gdb_index' section.
708325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
708425b3c049e70834cf33790a28643ab058b507b35cBen Cheng*/
708525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
708625b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
708725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
708825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
708925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
709025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %" PRId64 " bytes :\n"),
709125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
709225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
709325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
709425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
709525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
709625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
709725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
709825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
709925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ".gdb_index", elf_errmsg (-1));
710025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
710125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
710225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
710325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  // .gdb_index is always in little endian.
710425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
710525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  dbg = &dummy_dbg;
710625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
710725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
710825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = readp + data->d_size;
710925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
711025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
711125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
711225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid_data:
711325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("invalid data"));
711425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
711525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
711625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
711725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int32_t vers = read_4ubyte_unaligned (dbg, readp);
711825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" Version:         %" PRId32 "\n"), vers);
711925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
712025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  // The only difference between version 4 and version 5 is the
712125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  // hash used for generating the table.
712225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (vers < 4 || vers > 5)
712325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
712425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  unknown version, cannot parse section\n"));
712525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
712625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
712725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
712825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
712925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
713025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
713125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
713225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
713325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
713425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
713525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
713625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
713725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
713825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
713925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
714025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
714125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
714225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
714325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
714425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
714525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
714625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
714725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
714825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
714925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
715025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
715125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
715225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
715325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
715425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
715525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
715625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
715725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
715825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
715925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
716025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
716125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
716225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
716325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + cu_off;
716425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
716525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *nextp = data->d_buf + tu_off;
716625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nr = (nextp - readp) / 16;
716725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
716825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n CU list at offset %#" PRIx32
716925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu entries:\n"),
717025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cu_off, nr);
717125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
717225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t n = 0;
717325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp + 16 <= dataend && n < nr)
717425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
717525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t off = read_8ubyte_unaligned (dbg, readp);
717625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
717725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
717825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t len = read_8ubyte_unaligned (dbg, readp);
717925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
718025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
718125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%4zu] start: %0#8" PRIx64
718225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ", length: %5" PRIu64 "\n", n, off, len);
718325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
718425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
718525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
718625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + tu_off;
718725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nextp = data->d_buf + addr_off;
718825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nr = (nextp - readp) / 24;
718925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
719025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n TU list at offset %#" PRIx32
719125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu entries:\n"),
719225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  tu_off, nr);
719325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
719425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  n = 0;
719525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp + 24 <= dataend && n < nr)
719625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
719725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t off = read_8ubyte_unaligned (dbg, readp);
719825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
719925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
720025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t type = read_8ubyte_unaligned (dbg, readp);
720125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
720225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
720325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t sig = read_8ubyte_unaligned (dbg, readp);
720425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
720525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
720625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%4zu] CU offset: %5" PRId64
720725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ", type offset: %5" PRId64
720825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
720925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
721025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
721125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
721225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + addr_off;
721325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nextp = data->d_buf + sym_off;
721425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nr = (nextp - readp) / 20;
721525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
721625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n Address list at offset %#" PRIx32
721725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu entries:\n"),
721825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  addr_off, nr);
721925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
722025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  n = 0;
722125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp + 20 <= dataend && n < nr)
722225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
722325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t low = read_8ubyte_unaligned (dbg, readp);
722425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
722525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
722625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t high = read_8ubyte_unaligned (dbg, readp);
722725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
722825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
722925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t idx = read_4ubyte_unaligned (dbg, readp);
723025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 4;
723125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
723225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *l = format_dwarf_addr (dwflmod, 8, low);
723325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *h = format_dwarf_addr (dwflmod, 8, high - 1);
723425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
723525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      n, l, h, idx);
723625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
723725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
723825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
723925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + sym_off;
724025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nextp = data->d_buf + const_off;
724125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nr = (nextp - readp) / 8;
724225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
724325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n Symbol table at offset %#" PRIx32
724425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu slots:\n"),
724525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  addr_off, nr);
724625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
724725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  n = 0;
724825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp + 8 <= dataend && n < nr)
724925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
725025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t name = read_4ubyte_unaligned (dbg, readp);
725125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 4;
725225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
725325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t vector = read_4ubyte_unaligned (dbg, readp);
725425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 4;
725525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
725625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (name != 0 || vector != 0)
725725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
725825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *sym = data->d_buf + const_off + name;
725925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (sym > dataend))
726025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
726125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
726225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%4zu] symbol: %s, CUs: ", n, sym);
726325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
726425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *readcus = data->d_buf + const_off + vector;
726525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (readcus + 8 > dataend))
726625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
726725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
726825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
726925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (cus--)
727025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
727125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      uint32_t cu;
727225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      readcus += 4;
727325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cu = read_4ubyte_unaligned (dbg, readcus);
727425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf ("%" PRId32 "%s", cu, ((cus > 0) ? ", " : ""));
727525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
727625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n");
727725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
727825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
727925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
728025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
728125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
728225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
728325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
728425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
728525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Before we start the real work get a debug context descriptor.  */
728625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Addr dwbias;
728725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
728825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf dummy_dbg =
728925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
729025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .elf = ebl->elf,
729125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
729225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
729325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dbg == NULL)
729425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
729525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((print_debug_sections & ~section_exception) != 0)
729625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get debug context descriptor: %s"),
729725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       dwfl_errmsg (-1));
729825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((print_debug_sections & section_exception) == 0)
729925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return;
730025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dbg = &dummy_dbg;
730125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
730225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
730325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
730425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
730525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
730625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
730725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
730825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
730925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Look through all the sections for the debugging sections to print.  */
731025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
731125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
731225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
731325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
731425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
731525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
731625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
731725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
731825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  static const struct
731925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
732025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    const char *name;
732125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    enum section_e bitmask;
732225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    void (*fp) (Dwfl_Module *, Ebl *,
732325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
732425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  } debug_sections[] =
732525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
732625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define NEW_SECTION(name) \
732725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".debug_" #name, section_##name, print_debug_##name##_section }
732825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (abbrev),
732925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (aranges),
733025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (frame),
733125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (info),
733225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (types),
733325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (line),
733425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (loc),
733525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (pubnames),
733625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (str),
733725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (macinfo),
733825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (ranges),
733925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".eh_frame", section_frame | section_exception,
734025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		print_debug_frame_section },
734125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".eh_frame_hdr", section_frame | section_exception,
734225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		print_debug_frame_hdr_section },
734325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".gcc_except_table", section_frame | section_exception,
734425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		print_debug_exception_table },
734525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".gdb_index", section_gdb_index, print_gdb_index_section }
734625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    };
734725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const int ndebug_sections = (sizeof (debug_sections)
734825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       / sizeof (debug_sections[0]));
734925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *name = elf_strptr (ebl->elf, shstrndx,
735025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 shdr->sh_name);
735125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int n;
735225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
735325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (n = 0; n < ndebug_sections; ++n)
735425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (strcmp (name, debug_sections[n].name) == 0
735525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if USE_ZLIB
735625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		|| (name[0] == '.' && name[1] == 'z'
735725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && debug_sections[n].name[1] == 'd'
735825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
735925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
736025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		)
736125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
736225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if ((print_debug_sections | implicit_debug_sections)
736325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    & debug_sections[n].bitmask)
736425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
736525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
736625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
736725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
736825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
736925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
737025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  reset_listptr (&known_loclistptr);
737125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  reset_listptr (&known_rangelistptr);
737225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
737325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
737425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
737525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ITEM_INDENT		4
737625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ITEM_WRAP_COLUMN	150
737725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define REGISTER_WRAP_COLUMN	75
737825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
737925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
738025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   make the line exceed ITEM_WRAP_COLUMN.  Unpadded numbers look better
738125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   for the core items.  But we do not want the line breaks to depend on
738225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   the particular values.  */
738325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
738425b3c049e70834cf33790a28643ab058b507b35cBen Cheng__attribute__ ((format (printf, 7, 8)))
738525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_core_item (unsigned int colno, char sep, unsigned int wrap,
738625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 size_t name_width, const char *name,
738725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 size_t format_max, const char *format, ...)
738825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
738925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t len = strlen (name);
739025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (name_width < len)
739125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    name_width = len;
739225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
739325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t n = name_width + sizeof ": " - 1 + format_max;
739425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
739525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (colno == 0)
739625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
739725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%*s", ITEM_INDENT, "");
739825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = ITEM_INDENT + n;
739925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
740025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (colno + 2 + n < wrap)
740125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
740225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%c ", sep);
740325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno += 2 + n;
740425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
740525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
740625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
740725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("\n%*s", ITEM_INDENT, "");
740825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = ITEM_INDENT + n;
740925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
741025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
741125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf ("%s: %*s", name, (int) (name_width - len), "");
741225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
741325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  va_list ap;
741425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  va_start (ap, format);
741525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  vprintf (format, ap);
741625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  va_end (ap);
741725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
741825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
741925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
742025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
742125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const void *
742225b3c049e70834cf33790a28643ab058b507b35cBen Chengconvert (Elf *core, Elf_Type type, uint_fast16_t count,
742325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 void *value, const void *data, size_t size)
742425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
742525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data valuedata =
742625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
742725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_type = type,
742825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_buf = value,
742925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
743025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_version = EV_CURRENT,
743125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
743225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data indata =
743325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
743425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_type = type,
743525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_buf = (void *) data,
743625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_size = valuedata.d_size,
743725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_version = EV_CURRENT,
743825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
743925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
744025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
744125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 ? elf32_xlatetom : elf64_xlatetom)
744225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
744325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (d == NULL)
744425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
744525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
744625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
744725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return data + indata.d_size;
744825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
744925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
745025b3c049e70834cf33790a28643ab058b507b35cBen Chengtypedef uint8_t GElf_Byte;
745125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
745225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
745325b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
745425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  unsigned int colno, size_t *repeated_size)
745525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
745625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast16_t count = item->count ?: 1;
745725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
745825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define TYPES								      \
745925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4);			      \
746025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6);			      \
746125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11);			      \
746225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11);			      \
746325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20);		      \
746425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
746525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
746625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
746725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  union { TYPES; } value;
746825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
746925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
747025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *data = &value;
747125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
747225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t convsize = size;
747325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (repeated_size != NULL)
747425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
747525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
747625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
747725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data = alloca (*repeated_size);
747825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  count *= *repeated_size / size;
747925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  convsize = count * size;
748025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *repeated_size -= convsize;
748125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
748225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (item->count != 0 || item->format != '\n')
748325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*repeated_size -= size;
748425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
748525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
748625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  convert (core, item->type, count, data, desc + item->offset, convsize);
748725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
748825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Type type = item->type;
748925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (type == ELF_T_ADDR)
749025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
749125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
749225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (item->format)
749325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
749425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'd':
749525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 1);
749625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
749725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
749825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define DO_TYPE(NAME, Name, hex, dec, max)				      \
749925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case ELF_T_##NAME:						      \
750025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
750125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     0, item->name, max, dec, value.Name[0]); \
750225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break
750325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  TYPES;
750425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
750525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
750625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  abort ();
750725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
750825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
750925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
751025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'x':
751125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 1);
751225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
751325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
751425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define DO_TYPE(NAME, Name, hex, dec, max)				      \
751525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case ELF_T_##NAME:						      \
751625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
751725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     0, item->name, max, hex, value.Name[0]); \
751825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break
751925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  TYPES;
752025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
752125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
752225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  abort ();
752325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
752425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
752525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
752625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'b':
752725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'B':
752825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (size % sizeof (unsigned int) == 0);
752925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int nbits = count * size * 8;
753025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int pop = 0;
753125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
753225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	pop += __builtin_popcount (*i);
753325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool negate = pop > nbits / 2;
753425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned int bias = item->format == 'b';
753525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
753625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
753725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	char printed[(negate ? nbits - pop : pop) * 16];
753825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	char *p = printed;
753925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*p = '\0';
754025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
754125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
754225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
754325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    assert (size == sizeof (unsigned int) * 2);
754425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    for (unsigned int *i = data;
754525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 (void *) i < data + count * size; i += 2)
754625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
754725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		unsigned int w = i[1];
754825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		i[1] = i[0];
754925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		i[0] = w;
755025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
755125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
755225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
755325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	unsigned int lastbit = 0;
755425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	for (const unsigned int *i = data;
755525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (void *) i < data + count * size; ++i)
755625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
755725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    unsigned int bit = ((void *) i - data) * 8;
755825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    unsigned int w = negate ? ~*i : *i;
755925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    unsigned int run = 0;
756025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (w != 0)
756125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
756225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		int n = ffs (w);
756325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		w >>= n;
756425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		bit += n;
756525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
756625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (lastbit + 1 == bit)
756725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ++run;
756825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		else
756925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
757025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (lastbit == 0)
757125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      p += sprintf (p, "%u", bit - bias);
757225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else if (run == 0)
757325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      p += sprintf (p, ",%u", bit - bias);
757425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else
757525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
757625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    run = 0;
757725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
757825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
757925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		lastbit = bit;
758025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
758125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
758225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (lastbit > 0 && lastbit + 1 != nbits)
758325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  p += sprintf (p, "-%u", nbits - bias);
758425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
758525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
758625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 4 + nbits * 4,
758725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 negate ? "~<%s>" : "<%s>", printed);
758825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
758925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
759025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
759125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'T':
759225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case (char) ('T'|0x80):
759325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 2);
759425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word sec;
759525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word usec;
759625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t maxfmt = 7;
759725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
759825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
759925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define DO_TYPE(NAME, Name, hex, dec, max)				      \
760025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case ELF_T_##NAME:						      \
760125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    sec = value.Name[0];					      \
760225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    usec = value.Name[1];					      \
760325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    maxfmt += max;						      \
760425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break
760525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  TYPES;
760625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
760725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
760825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  abort ();
760925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
761025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (item->format == (char) ('T'|0x80)))
761125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
761225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This is a hack for an ill-considered 64-bit ABI where
761325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     tv_usec is actually a 32-bit field with 32 bits of padding
761425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     rounding out struct timeval.  We've already converted it as
761525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     a 64-bit field.  For little-endian, this just means the
761625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     high half is the padding; it's presumably zero, but should
761725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     be ignored anyway.  For big-endian, it means the 32-bit
761825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     field went into the high half of USEC.  */
761925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Ehdr ehdr_mem;
762025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
762125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
762225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    usec >>= 32;
762325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
762425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    usec &= UINT32_MAX;
762525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
762625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
762725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
762825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
762925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
763025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'c':
763125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 1);
763225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
763325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       1, "%c", value.Byte[0]);
763425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
763525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
763625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 's':
763725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
763825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       count, "%.*s", (int) count, value.Byte);
763925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
764025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
764125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case '\n':
764225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is a list of strings separated by '\n'.  */
764325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (item->count == 0);
764425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (repeated_size != NULL);
764525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (item->name == NULL);
764625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (item->offset >= *repeated_size))
764725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
764825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
764925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *s = desc + item->offset;
765025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size = *repeated_size - item->offset;
765125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *repeated_size = 0;
765225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (size > 0)
765325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
765425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *eol = memchr (s, '\n', size);
765525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int len = size;
765625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (eol != NULL)
765725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    len = eol - s;
765825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
765925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (eol == NULL)
766025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
766125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size -= eol + 1 - s;
766225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  s = eol + 1;
766325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
766425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
766525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = ITEM_WRAP_COLUMN;
766625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
766725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
766825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
766925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, "XXX not handling format '%c' for %s",
767025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     item->format, item->name);
767125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
767225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
767325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
767425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef TYPES
767525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
767625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
767725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
767825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
767925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
768025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort items by group, and by layout offset within each group.  */
768125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
768225b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_core_items (const void *a, const void *b)
768325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
768425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *p1 = a;
768525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *p2 = b;
768625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item1 = *p1;
768725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item2 = *p2;
768825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
768925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return ((item1->group == item2->group ? 0
769025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   : strcmp (item1->group, item2->group))
769125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: (int) item1->offset - (int) item2->offset);
769225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
769325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
769425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort item groups by layout offset of the first item in the group.  */
769525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
769625b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_core_item_groups (const void *a, const void *b)
769725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
769825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *const *p1 = a;
769925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *const *p2 = b;
770025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *group1 = *p1;
770125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *group2 = *p2;
770225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item1 = *group1;
770325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item2 = *group2;
770425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
770525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return (int) item1->offset - (int) item2->offset;
770625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
770725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
770825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
770925b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_items (Elf *core, const void *desc, size_t descsz,
771025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   const Ebl_Core_Item *items, size_t nitems)
771125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
771225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nitems == 0)
771325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 0;
771425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
771525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Sort to collect the groups together.  */
771625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *sorted_items[nitems];
771725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nitems; ++i)
771825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    sorted_items[i] = &items[i];
771925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
772025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
772125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Collect the unique groups and sort them.  */
772225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item **groups[nitems];
772325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  groups[0] = &sorted_items[0];
772425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t ngroups = 1;
772525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 1; i < nitems; ++i)
772625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (sorted_items[i]->group != sorted_items[i - 1]->group
772725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
772825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      groups[ngroups++] = &sorted_items[i];
772925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
773025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
773125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out all the groups.  */
773225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int colno = 0;
773325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
773425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const void *last = desc;
773525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nitems == 1)
773625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
773725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t size = descsz;
773825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
773925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (size == 0)
774025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return colno;
774125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      desc += descsz - size;
774225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      descsz = size;
774325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
774425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
774525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
774625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
774725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < ngroups; ++i)
774825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
774925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (const Ebl_Core_Item **item = groups[i];
775025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       (item < &sorted_items[nitems]
775125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& ((*item)->group == groups[i][0]->group
775225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    || !strcmp ((*item)->group, groups[i][0]->group)));
775325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       ++item)
775425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    colno = handle_core_item (core, *item, desc, colno, NULL);
775525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
775625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Force a line break at the end of the group.  */
775725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  colno = ITEM_WRAP_COLUMN;
775825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
775925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
776025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (descsz == 0)
776125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
776225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
776325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This set of items consumed a certain amount of the note's data.
776425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 If there is more data there, we have another unit of the same size.
776525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 Loop to print that out too.  */
776625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const Ebl_Core_Item *item = &items[nitems - 1];
776725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t eltsz = item->offset + gelf_fsize (core, item->type,
776825b3c049e70834cf33790a28643ab058b507b35cBen Cheng						item->count ?: 1, EV_CURRENT);
776925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
777025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int reps = -1;
777125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
777225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
777325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++reps;
777425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  desc += eltsz;
777525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  descsz -= eltsz;
777625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
777725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (descsz >= eltsz && !memcmp (desc, last, eltsz));
777825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
777925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (reps == 1)
778025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
778125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* For just one repeat, print it unabridged twice.  */
778225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  desc -= eltsz;
778325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  descsz += eltsz;
778425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
778525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (reps > 1)
778625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext ("\n%*s... <repeats %u more times> ..."),
778725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		ITEM_INDENT, "", reps);
778825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
778925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      last = desc;
779025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
779125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (descsz > 0);
779225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
779325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
779425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
779525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
779625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
779725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
779825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      unsigned int colno)
779925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
780025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  desc += regloc->offset;
780125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
780225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  abort ();			/* XXX */
780325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
780425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
780525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
780625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
780725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
780825b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_register (Ebl *ebl, Elf *core, int maxregname,
780925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      const Ebl_Register_Location *regloc, const void *desc,
781025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      unsigned int colno)
781125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
781225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (regloc->bits % 8 != 0)
781325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return handle_bit_registers (regloc, desc, colno);
781425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
781525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  desc += regloc->offset;
781625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
781725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
781825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
781925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char name[REGNAMESZ];
782025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int bits;
782125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int type;
782225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      register_info (ebl, reg, regloc, name, &bits, &type);
782325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
782425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define TYPES								      \
782525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4);			      \
782625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6);			      \
782725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11);		      \
782825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64, 20)
782925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
783025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define BITS(bits, xtype, sfmt, ufmt, max)				\
783125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint##bits##_t b##bits; int##bits##_t b##bits##s
783225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      union { TYPES; uint64_t b128[2]; } value;
783325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef	BITS
783425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
783525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
783625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
783725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_ATE_unsigned:
783825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_ATE_signed:
783925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_ATE_address:
784025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  switch (bits)
784125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
784225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define BITS(bits, xtype, sfmt, ufmt, max)				      \
784325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    case bits:							      \
784425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
784525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (type == DW_ATE_signed)				      \
784625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
784725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 maxregname, name,		      \
784825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 max, sfmt, value.b##bits##s);	      \
784925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else							      \
785025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
785125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 maxregname, name,		      \
785225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 max, ufmt, value.b##bits);	      \
785325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break
785425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
785525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    TYPES;
785625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
785725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    case 128:
785825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert (type == DW_ATE_unsigned);
785925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
786025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
786125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
786225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       maxregname, name,
786325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       34, "0x%.16" PRIx64 "%.16" PRIx64,
786425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       value.b128[!be], value.b128[be]);
786525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
786625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
786725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    default:
786825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      abort ();
786925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef	BITS
787025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
787125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
787225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
787325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
787425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Print each byte in hex, the whole thing in native byte order.  */
787525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (bits % 8 == 0);
787625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const uint8_t *bytes = desc;
787725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  desc += bits / 8;
787825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char hex[bits / 4 + 1];
787925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  hex[bits / 4] = '\0';
788025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int incr = 1;
788125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
788225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
788325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bytes += bits / 8 - 1;
788425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      incr = -1;
788525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
788625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t idx = 0;
788725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
788825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
788925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
789025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
789125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
789225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
789325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   maxregname, name,
789425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   2 + sizeof hex - 1, "0x%s", hex);
789525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
789625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
789725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      desc += regloc->pad;
789825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
789925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef TYPES
790025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
790125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
790225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
790325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
790425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
790525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
790625b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct register_info
790725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
790825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Register_Location *regloc;
790925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *set;
791025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char name[REGNAMESZ];
791125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int regno;
791225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int bits;
791325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int type;
791425b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
791525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
791625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
791725b3c049e70834cf33790a28643ab058b507b35cBen Chengregister_bitpos (const struct register_info *r)
791825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
791925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return (r->regloc->offset * 8
792025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  + ((r->regno - r->regloc->regno)
792125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     * (r->regloc->bits + r->regloc->pad * 8)));
792225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
792325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
792425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
792525b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_sets_by_info (const struct register_info *r1,
792625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      const struct register_info *r2)
792725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
792825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return ((int) r2->bits - (int) r1->bits
792925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: register_bitpos (r1) - register_bitpos (r2));
793025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
793125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
793225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort registers by set, and by size and layout offset within each set.  */
793325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
793425b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_registers (const void *a, const void *b)
793525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
793625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *r1 = a;
793725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *r2 = b;
793825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
793925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Unused elements sort last.  */
794025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (r1->regloc == NULL)
794125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return r2->regloc == NULL ? 0 : 1;
794225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (r2->regloc == NULL)
794325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
794425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
794525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
794625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: compare_sets_by_info (r1, r2));
794725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
794825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
794925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort register sets by layout offset of the first register in the set.  */
795025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
795125b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_register_sets (const void *a, const void *b)
795225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
795325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *const *p1 = a;
795425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *const *p2 = b;
795525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return compare_sets_by_info (*p1, *p2);
795625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
795725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
795825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
795925b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_registers (Ebl *ebl, Elf *core, const void *desc,
796025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       const Ebl_Register_Location *reglocs, size_t nregloc)
796125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
796225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nregloc == 0)
796325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 0;
796425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
796525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
796625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (maxnreg <= 0)
796725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
796825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < nregloc; ++i)
796925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (maxnreg < reglocs[i].regno + reglocs[i].count)
797025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  maxnreg = reglocs[i].regno + reglocs[i].count;
797125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (maxnreg > 0);
797225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
797325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
797425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct register_info regs[maxnreg];
797525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memset (regs, 0, sizeof regs);
797625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
797725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Sort to collect the sets together.  */
797825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int maxreg = 0;
797925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nregloc; ++i)
798025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    for (int reg = reglocs[i].regno;
798125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 reg < reglocs[i].regno + reglocs[i].count;
798225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 ++reg)
798325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
798425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	assert (reg < maxnreg);
798525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (reg > maxreg)
798625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  maxreg = reg;
798725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	struct register_info *info = &regs[reg];
798825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	info->regloc = &reglocs[i];
798925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	info->regno = reg;
799025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	info->set = register_info (ebl, reg, &reglocs[i],
799125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   info->name, &info->bits, &info->type);
799225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
799325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
799425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
799525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Collect the unique sets and sort them.  */
799625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  inline bool same_set (const struct register_info *a,
799725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const struct register_info *b)
799825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
799925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (a < &regs[maxnreg] && a->regloc != NULL
800025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    && b < &regs[maxnreg] && b->regloc != NULL
800125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    && a->bits == b->bits
800225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    && (a->set == b->set || !strcmp (a->set, b->set)));
800325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
800425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct register_info *sets[maxreg + 1];
800525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sets[0] = &regs[0];
800625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nsets = 1;
800725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int i = 1; i <= maxreg; ++i)
800825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
800925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sets[nsets++] = &regs[i];
801025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
801125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
801225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out all the sets.  */
801325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int colno = 0;
801425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nsets; ++i)
801525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
801625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Find the longest name of a register in this set.  */
801725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t maxname = 0;
801825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const struct register_info *end;
801925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (end = sets[i]; same_set (sets[i], end); ++end)
802025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
802125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t len = strlen (end->name);
802225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (len > maxname)
802325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    maxname = len;
802425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
802525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
802625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (const struct register_info *reg = sets[i];
802725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   reg < end;
802825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   reg += reg->regloc->count ?: 1)
802925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	colno = handle_core_register (ebl, core, maxname,
803025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      reg->regloc, desc, colno);
803125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
803225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Force a line break at the end of the group.  */
803325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = REGISTER_WRAP_COLUMN;
803425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
803525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
803625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
803725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
803825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
803925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
804025b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
804125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
804225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
804325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
804425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_error:
804525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
804625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
804725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
804825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
804925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nauxv; ++i)
805025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
805125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_auxv_t av_mem;
805225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
805325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (av == NULL)
805425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto elf_error;
805525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
805625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *name;
805725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *fmt;
805825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
805925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
806025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Unknown type.  */
806125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (av->a_un.a_val == 0)
806225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %" PRIu64 "\n", av->a_type);
806325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
806425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
806525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    av->a_type, av->a_un.a_val);
806625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
806725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
806825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	switch (fmt[0])
806925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
807025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case '\0':		/* Normally zero.  */
807125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (av->a_un.a_val == 0)
807225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
807325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("    %s\n", name);
807425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
807525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
807625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Fall through */
807725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'x':		/* hex */
807825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'p':		/* address */
807925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 's':		/* address of string */
808025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
808125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
808225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'u':
808325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
808425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
808525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'd':
808625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
808725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
808825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
808925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'b':
809025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
809125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    GElf_Xword bit = 1;
809225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    const char *pfx = "<";
809325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
809425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
809525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (av->a_un.a_val & bit)
809625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
809725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf ("%s%s", pfx, p);
809825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    pfx = " ";
809925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
810025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		bit <<= 1;
810125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
810225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (">\n");
810325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
810425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
810525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  default:
810625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    abort ();
810725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
810825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
810925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
811025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
811125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
811225b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
811325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  const char *name, const void *desc)
811425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
811525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Word regs_offset;
811625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nregloc;
811725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Register_Location *reglocs;
811825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nitems;
811925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *items;
812025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
812125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! ebl_core_note (ebl, nhdr, name,
812225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
812325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
812425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
812525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Pass 0 for DESCSZ when there are registers in the note,
812625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     so that the ITEMS array does not describe the whole thing.
812725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     For non-register notes, the actual descsz might be a multiple
812825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     of the unit size, not just exactly the unit size.  */
812925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int colno = handle_core_items (ebl->elf, desc,
813025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  nregloc == 0 ? nhdr->n_descsz : 0,
813125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  items, nitems);
813225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (colno != 0)
813325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    putchar_unlocked ('\n');
813425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
813525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
813625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 reglocs, nregloc);
813725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (colno != 0)
813825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    putchar_unlocked ('\n');
813925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
814025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
814125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
814225b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
814325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   GElf_Off start, Elf_Data *data)
814425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
814525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
814625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
814725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
814825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto bad_note;
814925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
815025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t offset = 0;
815125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Nhdr nhdr;
815225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t name_offset;
815325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t desc_offset;
815425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (offset < data->d_size
815525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 && (offset = gelf_getnote (data, offset,
815625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &nhdr, &name_offset, &desc_offset)) > 0)
815725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
815825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *name = data->d_buf + name_offset;
815925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *desc = data->d_buf + desc_offset;
816025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
816125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[100];
816225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf2[100];
816325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
816425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) nhdr.n_namesz, name, nhdr.n_descsz,
816525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_type == ET_CORE
816625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
816725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 buf, sizeof (buf))
816825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      : ebl_object_note_type_name (ebl, name, nhdr.n_type,
816925b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   buf2, sizeof (buf2)));
817025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
817125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Filter out invalid entries.  */
817225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (memchr (name, '\0', nhdr.n_namesz) != NULL
817325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX For now help broken Linux kernels.  */
817425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || 1)
817525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
817625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ehdr->e_type == ET_CORE)
817725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
817825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (nhdr.n_type == NT_AUXV
817925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
818025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      || (nhdr.n_namesz == 5 && name[4] == '\0'))
818125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && !memcmp (name, "CORE", 4))
818225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
818325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  start + desc_offset);
818425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
818525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_core_note (ebl, &nhdr, name, desc);
818625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
818725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
818825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
818925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
819025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
819125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
819225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (offset == data->d_size)
819325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
819425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
819525b3c049e70834cf33790a28643ab058b507b35cBen Cheng bad_note:
819625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  error (EXIT_FAILURE, 0,
819725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 gettext ("cannot get content of note section: %s"),
819825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 elf_errmsg (-1));
819925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
820025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
820125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
820225b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
820325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
820425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If we have section headers, just look for SHT_NOTE sections.
820525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     In a debuginfo file, the program headers are not reliable.  */
820625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shnum != 0)
820725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
820825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the section header string table index.  */
820925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t shstrndx;
821025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
821125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0,
821225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("cannot get section header string table index"));
821325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
821425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = NULL;
821525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
821625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
821725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr shdr_mem;
821825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
821925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
822025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
822125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Not what we are looking for.  */
822225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
822325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
822425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\
822525b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
822625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn),
822725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
822825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_size, shdr->sh_offset);
822925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
823025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
823125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     elf_getdata (scn, NULL));
823225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
823325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
823425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
823525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
823625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We have to look through the program header to find the note
823725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     sections.  There can be more than one.  */
823825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < phnum; ++cnt)
823925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
824025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr mem;
824125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
824225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
824325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (phdr == NULL || phdr->p_type != PT_NOTE)
824425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Not what we are looking for.  */
824525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
824625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
824725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
824825b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
824925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_filesz, phdr->p_offset);
825025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
825125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      handle_notes_data (ebl, ehdr, phdr->p_offset,
825225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 elf_getdata_rawchunk (ebl->elf,
825325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       phdr->p_offset, phdr->p_filesz,
825425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       ELF_T_NHDR));
825525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
825625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
825725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
825825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
825925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
826025b3c049e70834cf33790a28643ab058b507b35cBen Chenghex_dump (const uint8_t *data, size_t len)
826125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
826225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t pos = 0;
826325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (pos < len)
826425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
826525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  0x%08Zx ", pos);
826625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
826725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const size_t chunk = MIN (len - pos, 16);
826825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
826925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < chunk; ++i)
827025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (i % 4 == 3)
827125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%02x ", data[pos + i]);
827225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	else
827325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%02x", data[pos + i]);
827425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
827525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (chunk < 16)
827625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
827725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
827825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < chunk; ++i)
827925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
828025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned char b = data[pos + i];
828125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%c", isprint (b) ? b : '.');
828225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
828325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
828425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar ('\n');
828525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      pos += chunk;
828625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
828725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
828825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
828925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
829025b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
829125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
829225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
829325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
829425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), name);
829525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
829625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
829725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
829825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (data == NULL)
829925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
830025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_ndxscn (scn), name, elf_errmsg (-1));
830125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
830225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
830325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
830425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   " bytes at offset %#0" PRIx64 ":\n"),
830525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn), name,
830625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_size, shdr->sh_offset);
830725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  hex_dump (data->d_buf, data->d_size);
830825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
830925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
831025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
831125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
831225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
831325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
831425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
831525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
831625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
831725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), name);
831825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
831925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
832025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
832125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (data == NULL)
832225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
832325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_ndxscn (scn), name, elf_errmsg (-1));
832425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
832525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
832625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
832725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   " bytes at offset %#0" PRIx64 ":\n"),
832825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn), name,
832925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_size, shdr->sh_offset);
833025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
833125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *start = data->d_buf;
833225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *const limit = start + data->d_size;
833325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  do
833425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
833525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const char *end = memchr (start, '\0', limit - start);
833625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const size_t pos = start - (const char *) data->d_buf;
833725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (end == NULL))
833825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
833925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf ("  [%6Zx]- %.*s\n",
834025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  pos, (int) (limit - start), start);
834125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
834225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
834325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf ("  [%6Zx]  %s\n", pos, start);
834425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      start = end + 1;
834525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    } while (start < limit);
834625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
834725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
834825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
834925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
835025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
835125b3c049e70834cf33790a28643ab058b507b35cBen Chengfor_each_section_argument (Elf *elf, const struct section_argument *list,
835225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
835325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 const char *name))
835425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
835525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
835625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
835725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
835825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
835925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
836025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
836125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (const struct section_argument *a = list; a != NULL; a = a->next)
836225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
836325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn;
836425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
836525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *name = NULL;
836625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
836725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *endp = NULL;
836825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned long int shndx = strtoul (a->arg, &endp, 0);
836925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp != a->arg && *endp == '\0')
837025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
837125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn = elf_getscn (elf, shndx);
837225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (scn == NULL)
837325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
837425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
837525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
837625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
837725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
837825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
837925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
838025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   elf_errmsg (-1));
838125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
838225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
838325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
838425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
838525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Need to look up the section by name.  */
838625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn = NULL;
838725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool found = false;
838825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while ((scn = elf_nextscn (elf, scn)) != NULL)
838925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
839025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
839125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
839225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
839325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (name == NULL)
839425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
839525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!strcmp (name, a->arg))
839625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
839725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  found = true;
839825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (*dump) (scn, &shdr_mem, name);
839925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
840025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
840125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
840225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (!found) && !a->implicit)
840325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
840425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
840525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
840625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
840725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
840825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
840925b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_data (Ebl *ebl)
841025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
841125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
841225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
841325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
841425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
841525b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_strings (Ebl *ebl)
841625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
841725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for_each_section_argument (ebl->elf, string_sections, &print_string_section);
841825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
841925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
842025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
842125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_strings (Ebl *ebl)
842225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
842325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
842425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
842525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
842625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
842725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
842825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
842925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn;
843025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr shdr_mem;
843125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *name;
843225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  scn = NULL;
843325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
843425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
843525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (gelf_getshdr (scn, &shdr_mem) == NULL)
843625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
843725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
843825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr_mem.sh_type != SHT_PROGBITS
843925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || !(shdr_mem.sh_flags & SHF_STRINGS))
844025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
844125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
844225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
844325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (name == NULL)
844425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
844525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
844625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_string_section (scn, &shdr_mem, name);
844725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
844825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
844925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
845025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
845125b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_archive_index (Elf *elf, const char *fname)
845225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
845325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t narsym;
845425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
845525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (arsym == NULL)
845625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
845725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int result = elf_errno ();
845825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (result != ELF_E_NO_INDEX))
845925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0,
846025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("cannot get symbol index of archive '%s': %s"),
846125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       fname, elf_errmsg (result));
846225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
846325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
846425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
846525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
846625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
846725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
846825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fname, narsym);
846925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
847025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t as_off = 0;
847125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
847225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
847325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (s->as_off != as_off)
847425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
847525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  as_off = s->as_off;
847625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
847725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf *subelf;
847825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (elf_rand (elf, as_off) == 0)
847925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
848025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   == NULL))
848125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
848225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (1)
848325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
848425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (EXIT_FAILURE, 0,
848525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     gettext ("cannot extract member at offset %Zu in '%s': %s"),
848625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     as_off, fname, elf_errmsg (-1));
848725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
848825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const Elf_Arhdr *h = elf_getarhdr (subelf);
848925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
849025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
849125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
849225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_end (subelf);
849325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
849425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
849525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("\t%s\n", s->as_name);
849625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
849725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
849825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
849925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "debugpred.h"
8500