125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print information from ELF file in human-readable form.
203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   Copyright (C) 1999-2014 Red Hat, Inc.
303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is part of elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is free software; you can redistribute it and/or modify
703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   it under the terms of the GNU General Public License as published by
803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   the Free Software Foundation; either version 3 of the License, or
903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   (at your option) any later version.
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   elfutils is distributed in the hope that it will be useful, but
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   GNU General Public License for more details.
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   You should have received a copy of the GNU General Public License
1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <argp.h>
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ctype.h>
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <dwarf.h>
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h>
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h>
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h>
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h>
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <langinfo.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libdw.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libdwfl.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <locale.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdarg.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <time.h>
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h>
4503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <signal.h>
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/libelfP.h"
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/common.h"
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libebl/libeblP.h"
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdw/libdwP.h"
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdwfl/libdwflP.h"
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libdw/memory-access.h"
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include "../libdw/known-dwarf.h"
5603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Name and version of program.  */
5925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_version (FILE *stream, struct argp_state *state);
6025b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Bug report address.  */
6325b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* argp key value for --elf-section, non-ascii.  */
6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ELF_INPUT_SECTION 256
6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Definitions of arguments for argp functions.  */
6925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct argp_option options[] =
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
7203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
7303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       "input data"), 0 },
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "all", 'a', NULL, 0,
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "histogram", 'I', NULL, 0,
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display histogram of bucket list lengths"), 0 },
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "arch-specific", 'A', NULL, 0,
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display architecture specific information, if any"), 0 },
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "exception", 'e', NULL, 0,
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display sections for exception handling"), 0 },
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display DWARF section content.  SECTION can be one of abbrev, "
9803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       "aranges, decodedaranges, frame, gdb_index, info, loc, line, "
9903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "hex-dump", 'x', "SECTION", 0,
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Print string contents of sections"), 0 },
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "archive-index", 'c', NULL, 0,
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Display the symbol index of an archive"), 0 },
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Output control:"), 0 },
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "numeric-addresses", 'N', NULL, 0,
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Do not find symbol names for addresses in DWARF data"), 0 },
11103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  { "unresolved-address-offsets", 'U', NULL, 0,
11203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "wide", 'W', NULL, 0,
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Ignored for compatibility (lines always wide)"), 0 },
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, NULL, 0 }
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Short description of program.  */
11925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char doc[] = N_("\
12025b3c049e70834cf33790a28643ab058b507b35cBen ChengPrint information from ELF file in human-readable form.");
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Strings for arguments in help texts.  */
12325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char args_doc[] = N_("FILE...");
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototype for option handler.  */
12625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Data structure to communicate with argp functions.  */
12925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp argp =
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  options, parse_opt, args_doc, doc, NULL, NULL, NULL
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* If non-null, the section from which we should read to (compressed) ELF.  */
13503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *elf_input_section = NULL;
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Flags set by the option controlling the output.  */
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if dynamic segment should be printed.  */
14025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_dynamic_table;
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the file header should be printed.  */
14325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_file_header;
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the program headers should be printed.  */
14625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_program_header;
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if relocations should be printed.  */
14925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_relocations;
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the section headers should be printed.  */
15225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_section_header;
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the symbol table should be printed.  */
15525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_symbol_table;
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the version information should be printed.  */
15825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_version_info;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if section groups should be printed.  */
16125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_section_groups;
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if bucket list length histogram should be printed.  */
16425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_histogram;
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if the architecture specific data should be printed.  */
16725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_arch;
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if note section content should be printed.  */
17025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_notes;
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if SHF_STRINGS section content should be printed.  */
17325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_string_sections;
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if archive index should be printed.  */
17625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_archive_index;
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if any of the control options except print_archive_index is set.  */
17925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool any_control_option;
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if we should print addresses from DWARF in symbolic form.  */
18225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_address_names = true;
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* True if we should print raw values instead of relativized addresses.  */
18503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool print_unresolved_addresses = false;
18603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
18703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* True if we should print the .debug_aranges section using libdw.  */
18803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool decodedaranges = false;
18903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
19003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* True if we should print the .debug_aranges section using libdw.  */
19103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool decodedline = false;
19203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Select printing of debugging sections.  */
19425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum section_e
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_abbrev = 1,		/* .debug_abbrev  */
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_aranges = 2,		/* .debug_aranges  */
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_frame = 4,		/* .debug_frame or .eh_frame & al.  */
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_info = 8,		/* .debug_info, .debug_types  */
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_types = section_info,
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_line = 16,		/* .debug_line  */
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_loc = 32,		/* .debug_loc  */
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_pubnames = 64,	/* .debug_pubnames  */
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_str = 128,		/* .debug_str  */
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_macinfo = 256,	/* .debug_macinfo  */
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_ranges = 512, 	/* .debug_ranges  */
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_exception = 1024,	/* .eh_frame & al.  */
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_gdb_index = 2048,	/* .gdb_index  */
20903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  section_macro = 4096,		/* .debug_macro  */
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  section_all = (section_abbrev | section_aranges | section_frame
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 | section_info | section_line | section_loc
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 | section_pubnames | section_str | section_macinfo
21303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 | section_ranges | section_exception | section_gdb_index
21403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 | section_macro)
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} print_debug_sections, implicit_debug_sections;
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Select hex dumping of sections.  */
21825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument *dump_data_sections;
21925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument **dump_data_sections_tail = &dump_data_sections;
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Select string dumping of sections.  */
22225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument *string_sections;
22325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct section_argument **string_sections_tail = &string_sections;
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22525b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct section_argument
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct section_argument *next;
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *arg;
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool implicit;
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Numbers of sections and program headers in the file.  */
23325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t shnum;
23425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t phnum;
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Declarations of local functions.  */
23825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void process_file (int fd, const char *fname, bool only_one);
23925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void process_elf_file (Dwfl_Module *dwflmod, int fd);
24025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
24125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
24225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
24325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_scngrp (Ebl *ebl);
24425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_dynamic (Ebl *ebl);
24525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
24625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       GElf_Shdr *shdr);
24825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				GElf_Shdr *shdr);
25025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_symtab (Ebl *ebl, int type);
25125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
25225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_verinfo (Ebl *ebl);
25325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
25425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
25525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_versym (Ebl *ebl, Elf_Scn *scn,
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   GElf_Shdr *shdr);
25725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
25825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_hash (Ebl *ebl);
25925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
26025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_liblist (Ebl *ebl);
26125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
26225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void dump_data (Ebl *ebl);
26325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void dump_strings (Ebl *ebl);
26425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_strings (Ebl *ebl);
26525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void dump_archive_index (Elf *, const char *);
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26825b3c049e70834cf33790a28643ab058b507b35cBen Chengint
26925b3c049e70834cf33790a28643ab058b507b35cBen Chengmain (int argc, char *argv[])
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set locale.  */
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  setlocale (LC_ALL, "");
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the message catalog.  */
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  textdomain (PACKAGE_TARNAME);
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Parse and process arguments.  */
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int remaining;
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Before we start tell the ELF library which version we are using.  */
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_version (EV_CURRENT);
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now process all the files given at the command line.  */
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool only_one = remaining + 1 == argc;
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Open the file.  */
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int fd = open (argv[remaining], O_RDONLY);
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (fd == -1)
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, errno, gettext ("cannot open input file"));
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      process_file (fd, argv[remaining], only_one);
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      close (fd);
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (++remaining < argc);
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return error_message_count != 0;
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle program arguments.  */
30725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t
30825b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_opt (int key, char *arg,
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   struct argp_state *state __attribute__ ((unused)))
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void add_dump_section (const char *name, bool implicit)
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    struct section_argument *a = xmalloc (sizeof *a);
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    a->arg = name;
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    a->next = NULL;
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    a->implicit = implicit;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    struct section_argument ***tailp
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    **tailp = a;
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *tailp = &a->next;
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (key)
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'a':
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_file_header = true;
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_program_header = true;
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_relocations = true;
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_header = true;
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_symbol_table = true;
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_version_info = true;
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_dynamic_table = true;
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_groups = true;
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_histogram = true;
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_arch = true;
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_notes = true;
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      implicit_debug_sections |= section_exception;
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (".strtab", true);
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (".dynstr", true);
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (".comment", true);
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'A':
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_arch = true;
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'd':
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_dynamic_table = true;
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'e':
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_debug_sections |= section_exception;
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'g':
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_groups = true;
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'h':
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_file_header = true;
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'I':
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_histogram = true;
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'l':
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_program_header = true;
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'n':
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_notes = true;
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'r':
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_relocations = true;
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     break;
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'S':
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_section_header = true;
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 's':
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_symbol_table = true;
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'V':
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_version_info = true;
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'c':
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_archive_index = true;
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'w':
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (arg == NULL)
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections = section_all;
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "abbrev") == 0)
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_abbrev;
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "aranges") == 0)
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_aranges;
40103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else if (strcmp (arg, "decodedaranges") == 0)
40203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
40303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  print_debug_sections |= section_aranges;
40403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  decodedaranges = true;
40503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "ranges") == 0)
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_debug_sections |= section_ranges;
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  implicit_debug_sections |= section_info;
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_frame;
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "info") == 0)
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_info;
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "loc") == 0)
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_debug_sections |= section_loc;
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  implicit_debug_sections |= section_info;
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "line") == 0)
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_line;
42203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else if (strcmp (arg, "decodedline") == 0)
42303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
42403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  print_debug_sections |= section_line;
42503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  decodedline = true;
42603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "pubnames") == 0)
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_pubnames;
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "str") == 0)
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_str;
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "macinfo") == 0)
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_macinfo;
43303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else if (strcmp (arg, "macro") == 0)
43403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	print_debug_sections |= section_macro;
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "exception") == 0)
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_exception;
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (strcmp (arg, "gdb_index") == 0)
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	print_debug_sections |= section_gdb_index;
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   arg);
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE,
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     program_invocation_short_name);
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  exit (1);
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'p':
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (arg == NULL)
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_string_sections = true;
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Fall through.  */
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'x':
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      add_dump_section (arg, false);
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      any_control_option = true;
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'N':
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_address_names = false;
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
46403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case 'U':
46503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      print_unresolved_addresses = true;
46603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      break;
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ARGP_KEY_NO_ARGS:
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs (gettext ("Missing file name.\n"), stderr);
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto do_argp_help;
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ARGP_KEY_FINI:
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (! any_control_option && ! print_archive_index)
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs (gettext ("No operation specified.\n"), stderr);
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	do_argp_help:
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE,
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     program_invocation_short_name);
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  exit (EXIT_FAILURE);
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'W':			/* Ignored.  */
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
48203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case ELF_INPUT_SECTION:
48303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (arg == NULL)
48403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	elf_input_section = ".gnu_debugdata";
48503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else
48603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	elf_input_section = arg;
48703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      break;
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ARGP_ERR_UNKNOWN;
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the version information.  */
49625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
49725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("\
50125b3c049e70834cf33790a28643ab058b507b35cBen ChengCopyright (C) %s Red Hat, Inc.\n\
50225b3c049e70834cf33790a28643ab058b507b35cBen ChengThis is free software; see the source for copying conditions.  There is NO\n\
50325b3c049e70834cf33790a28643ab058b507b35cBen Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng"), "2012");
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Create a file descriptor to read the data from the
51003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   elf_input_section given a file descriptor to an ELF file.  */
51103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int
51203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesopen_input_section (int fd)
51303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
51403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t shnums;
51503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t cnt;
51603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t shstrndx;
51703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
51803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (elf == NULL)
51903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
52003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
52103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     elf_errmsg (-1));
52203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return -1;
52303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
52403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
52503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (elf_getshdrnum (elf, &shnums) < 0)
52603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
52703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("cannot determine number of sections: %s"),
52803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     elf_errmsg (-1));
52903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    open_error:
53003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      elf_end (elf);
53103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return -1;
53203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
53303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
53403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
53503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
53603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("cannot get section header string table index"));
53703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      goto open_error;
53803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
53903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
54003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (cnt = 0; cnt < shnums; ++cnt)
54103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
54203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Elf_Scn *scn = elf_getscn (elf, cnt);
54303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (scn == NULL)
54403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
54503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("cannot get section: %s"),
54603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 elf_errmsg (-1));
54703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  goto open_error;
54803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
54903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
55003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      GElf_Shdr shdr_mem;
55103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
55203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (shdr == NULL))
55303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
55403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("cannot get section header: %s"),
55503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 elf_errmsg (-1));
55603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  goto open_error;
55703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
55803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
55903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
56003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (sname == NULL)
56103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
56203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("cannot get section name"));
56303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  goto open_error;
56403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
56503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
56603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (strcmp (sname, elf_input_section) == 0)
56703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
56803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Elf_Data *data = elf_rawdata (scn, NULL);
56903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (data == NULL)
57003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
57103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      error (0, 0, gettext ("cannot get %s content: %s"),
57203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		     sname, elf_errmsg (-1));
57303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto open_error;
57403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
57503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
57603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* Create (and immediately unlink) a temporary file to store
57703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     section data in to create a file descriptor for it.  */
57803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
57903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  static const char suffix[] = "/readelfXXXXXX";
58003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  int tmplen = strlen (tmpdir) + sizeof (suffix);
58103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *tempname = alloca (tmplen);
58203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  sprintf (tempname, "%s%s", tmpdir, suffix);
58303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
58403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  int sfd = mkstemp (tempname);
58503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (sfd == -1)
58603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
58703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      error (0, 0, gettext ("cannot create temp file '%s'"),
58803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		     tempname);
58903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto open_error;
59003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
59103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  unlink (tempname);
59203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
59303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  ssize_t size = data->d_size;
59403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (write_retry (sfd, data->d_buf, size) != size)
59503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
59603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      error (0, 0, gettext ("cannot write section data"));
59703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto open_error;
59803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
59903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
60003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (elf_end (elf) != 0)
60103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
60203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      error (0, 0, gettext ("error while closing Elf descriptor: %s"),
60303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		     elf_errmsg (-1));
60403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      return -1;
60503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
60603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
60703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (lseek (sfd, 0, SEEK_SET) == -1)
60803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
60903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      error (0, 0, gettext ("error while rewinding file descriptor"));
61003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      return -1;
61103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
61203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
61303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return sfd;
61403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
61503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
61603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
61703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Named section not found.  */
61803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (elf_end (elf) != 0)
61903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (0, 0, gettext ("error while closing Elf descriptor: %s"),
62003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   elf_errmsg (-1));
62103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return -1;
62203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
62303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Check if the file is an archive, and if so dump its index.  */
62525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
62625b3c049e70834cf33790a28643ab058b507b35cBen Chengcheck_archive_index (int fd, const char *fname, bool only_one)
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create an `Elf' descriptor.  */
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf == NULL)
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   elf_errmsg (-1));
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_kind (elf) == ELF_K_AR)
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!only_one)
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("\n%s:\n\n", fname);
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  dump_archive_index (elf, fname);
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0,
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("'%s' is not an archive, cannot print archive index"),
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       fname);
64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Now we can close the descriptor.  */
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_end (elf) != 0)
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("error while closing Elf descriptor: %s"),
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Trivial callback used for checking if we opened an archive.  */
65425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
65525b3c049e70834cf33790a28643ab058b507b35cBen Chengcount_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       void **userdata __attribute__ ((unused)),
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       const char *name __attribute__ ((unused)),
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       Dwarf_Addr base __attribute__ ((unused)),
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       void *arg)
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*(bool *) arg)
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return DWARF_CB_ABORT;
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *(bool *) arg = true;
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return DWARF_CB_OK;
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66725b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct process_dwflmod_args
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int fd;
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool only_one;
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
67325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
67425b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_dwflmod (Dwfl_Module *dwflmod,
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 void **userdata __attribute__ ((unused)),
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 const char *name __attribute__ ((unused)),
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 Dwarf_Addr base __attribute__ ((unused)),
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 void *arg)
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct process_dwflmod_args *a = arg;
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Print the file name.  */
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!a->only_one)
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *fname;
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("\n%s:\n\n", fname);
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  process_elf_file (dwflmod, a->fd);
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return DWARF_CB_OK;
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Stub libdwfl callback, only the ELF handle already open is ever used.
69703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   Only used for finding the alternate debug file if the Dwarf comes from
69803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   the main file.  We are not interested in separate debuginfo.  */
69925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
70003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesfind_no_debuginfo (Dwfl_Module *mod,
70103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   void **userdata,
70203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   const char *modname,
70303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   Dwarf_Addr base,
70403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   const char *file_name,
70503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   const char *debuglink_file,
70603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   GElf_Word debuglink_crc,
70703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   char **debuginfo_file_name)
70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
70903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Addr dwbias;
71003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
71103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
71203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* We are only interested if the Dwarf has been setup on the main
71303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     elf file but is only missing the alternate debug link.  If dwbias
71403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     hasn't even been setup, this is searching for separate debuginfo
71503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     for the main elf.  We don't care in that case.  */
71603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (dwbias == (Dwarf_Addr) -1)
71703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return -1;
71803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
71903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
72003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       file_name, debuglink_file,
72103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       debuglink_crc, debuginfo_file_name);
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process one input file.  */
72525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
72625b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_file (int fd, const char *fname, bool only_one)
72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_archive_index)
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    check_archive_index (fd, fname, only_one);
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!any_control_option)
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (elf_input_section != NULL)
73503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
73603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* Replace fname and fd with section content. */
73703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
73803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      sprintf (fnname, "%s:%s", fname, elf_input_section);
73903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      fd = open_input_section (fd);
74003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (fd == -1)
74103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes        {
74203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes          error (0, 0, gettext ("No such section '%s' in '%s'"),
74303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 elf_input_section, fname);
74403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes          return;
74503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes        }
74603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      fname = fnname;
74703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
74803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Duplicate an fd for dwfl_report_offline to swallow.  */
75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int dwfl_fd = dup (fd);
75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (dwfl_fd < 0))
75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, errno, "dup");
75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Use libdwfl in a trivial way to open the libdw handle for us.
75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     This takes care of applying relocations to DWARF data in ET_REL files.  */
75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const Dwfl_Callbacks callbacks =
75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .section_address = dwfl_offline_section_address,
75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .find_debuginfo = find_no_debuginfo
76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwfl *dwfl = dwfl_begin (&callbacks);
76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (dwfl != NULL))
76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Let 0 be the logical address of the file (or first in archive).  */
76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    dwfl->offline_next_address = 0;
76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct stat64 st;
76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (fstat64 (dwfl_fd, &st) != 0)
76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, errno, gettext ("cannot stat input file"));
77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (unlikely (st.st_size == 0))
77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("input file is empty"));
77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("failed reading '%s': %s"),
77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       fname, dwfl_errmsg (-1));
77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      close (dwfl_fd);		/* Consumed on success, not on failure.  */
77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dwfl_report_end (dwfl, NULL, NULL);
78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (only_one)
78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool seen = false;
78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Process the one or more modules gleaned from this file.  */
78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  dwfl_end (dwfl);
79303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
79403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Need to close the replaced fd if we created it.  Caller takes
79503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     care of original.  */
79603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (elf_input_section != NULL)
79703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    close (fd);
79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Process one ELF file.  */
80225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
80325b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_elf_file (Dwfl_Module *dwflmod, int fd)
80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr dwflbias;
80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr ehdr_mem;
80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr == NULL)
81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    elf_error:
81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Ebl *ebl = ebl_openbackend (elf);
81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ebl == NULL))
82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ebl_error:
82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, errno, gettext ("cannot create EBL handle"));
82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Determine the number of sections.  */
82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot determine number of sections: %s"),
83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   elf_errmsg (-1));
83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Determine the number of phdrs.  */
83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot determine number of program headers: %s"),
83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   elf_errmsg (-1));
83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     and may have applied relocation to some sections.
84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     So we need to get a fresh Elf handle on the file to display those.  */
84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool print_unrelocated = (print_section_header
84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    || print_relocations
84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    || dump_data_sections != NULL
84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    || print_notes);
84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *pure_elf = NULL;
84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Ebl *pure_ebl = ebl;
84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_type == ET_REL && print_unrelocated)
84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Read the file afresh.  */
85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off64_t aroff = elf_getaroff (elf);
85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (aroff > 0)
85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Archive member.  */
85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (void) elf_rand (pure_elf, aroff);
85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_end (pure_elf);
85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  pure_elf = armem;
86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (pure_elf == NULL)
86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto elf_error;
86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      pure_ebl = ebl_openbackend (pure_elf);
86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (pure_ebl == NULL)
86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto ebl_error;
86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_file_header)
86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_ehdr (ebl, ehdr);
87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_section_header)
87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_shdr (pure_ebl, ehdr);
87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_program_header)
87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_phdr (ebl, ehdr);
87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_section_groups)
87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_scngrp (ebl);
87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_dynamic_table)
87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_dynamic (ebl);
87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_relocations)
87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_relocs (pure_ebl, ehdr);
88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_histogram)
88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    handle_hash (ebl);
88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_symbol_table)
88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_symtab (ebl, SHT_DYNSYM);
88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_version_info)
88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_verinfo (ebl);
88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_symbol_table)
88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_symtab (ebl, SHT_SYMTAB);
88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_arch)
88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_liblist (ebl);
89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_arch)
89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_attributes (ebl, ehdr);
89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dump_data_sections != NULL)
89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    dump_data (pure_ebl);
89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (string_sections != NULL)
89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    dump_strings (ebl);
89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((print_debug_sections | implicit_debug_sections) != 0)
89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_debug (dwflmod, ebl, ehdr);
89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_notes)
89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    handle_notes (pure_ebl, ehdr);
90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_string_sections)
90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    print_strings (ebl);
90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ebl_closebackend (ebl);
90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (pure_ebl != ebl)
90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ebl_closebackend (pure_ebl);
90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf_end (pure_elf);
90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print file type.  */
91425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
91525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_file_type (unsigned short int e_type)
91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (e_type <= ET_CORE))
91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      static const char *const knowntypes[] =
92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("NONE (None)"),
92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("REL (Relocatable file)"),
92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("EXEC (Executable file)"),
92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("DYN (Shared object file)"),
92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	N_("CORE (Core file)")
92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      };
92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext (knowntypes[e_type]));
92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
92925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("OS Specific: (%x)\n"),  e_type);
93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("Processor Specific: (%x)\n"),  e_type);
93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts ("???");
93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print ELF header.  */
93925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
94025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (" %02hhx", ehdr->e_ident[cnt]);
94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n  Class:                             %s\n"),
94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : "\?\?\?");
95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Data:                              %s\n"),
95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? "2's complement, little endian"
95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? "2's complement, big endian" : "\?\?\?");
95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Ident Version:                     %hhd %s\n"),
95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_VERSION],
95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : "(\?\?\?)");
96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char buf[512];
96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  OS/ABI:                            %s\n"),
96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  ABI Version:                       %hhd\n"),
96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ident[EI_ABIVERSION]);
96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("  Type:                              "), stdout);
97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_file_type (ehdr->e_type);
97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Machine:                           %s\n"), ebl->name);
97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Version:                           %d %s\n"),
97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_version,
97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_entry);
98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_phoff, gettext ("(bytes into file)"));
98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_shoff, gettext ("(bytes into file)"));
98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Flags:                             %s\n"),
98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_ehsize, gettext ("(bytes)"));
99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_phentsize, gettext ("(bytes)"));
99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Number of program headers entries: %" PRId16),
99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_phnum);
99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_phnum == PN_XNUM)
99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL)
100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" (%" PRIu32 " in [0].sh_info)"),
100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint32_t) shdr->sh_info);
100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked (gettext (" ([0] not available)"), stdout);
100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputc_unlocked ('\n', stdout);
100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_shentsize, gettext ("(bytes)"));
101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("  Number of section headers entries: %" PRId16),
101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ehdr->e_shnum);
101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_shnum == 0)
101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL)
102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint32_t) shdr->sh_size);
102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked (gettext (" ([0] not available)"), stdout);
102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputc_unlocked ('\n', stdout);
102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL)
103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* We managed to get the zeroth section.  */
103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (uint32_t) shdr->sh_link);
103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  buf[sizeof (buf) - 1] = '\0';
103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      buf);
104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ehdr->e_shstrndx);
104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
105125b3c049e70834cf33790a28643ab058b507b35cBen Chengget_visibility_type (int value)
105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (value)
105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_DEFAULT:
105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "DEFAULT";
105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_INTERNAL:
105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "INTERNAL";
105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_HIDDEN:
106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "HIDDEN";
106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case STV_PROTECTED:
106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "PROTECTED";
106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return "???";
106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the section headers.  */
107025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
107125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cnt;
107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! print_file_header)
107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
107825b3c049e70834cf33790a28643ab058b507b35cBen ChengThere are %d section headers, starting at offset %#" PRIx64 ":\n\
107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\n"),
108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ehdr->e_shnum, ehdr->e_shoff);
108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (gettext ("Section Headers:"));
108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (cnt = 0; cnt < shnum; ++cnt)
109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (scn == NULL))
109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the section header.  */
110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (shdr == NULL))
110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char flagbuf[20];
111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *cp = flagbuf;
111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_WRITE)
111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'W';
111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_ALLOC)
111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'A';
111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_EXECINSTR)
111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'X';
111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_MERGE)
111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'M';
111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_STRINGS)
112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'S';
112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_INFO_LINK)
112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'I';
112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_LINK_ORDER)
112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'L';
112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_OS_NONCONFORMING)
112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'N';
112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_GROUP)
112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'G';
112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_TLS)
113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'T';
113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_ORDERED)
113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'O';
113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_flags & SHF_EXCLUDE)
113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*cp++ = 'E';
113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *cp = '\0';
113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[128];
113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      " %2" PRId64 "\n",
114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cnt,
114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ?: "<corrupt>",
114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
114725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_addralign);
115025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
115125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputc_unlocked ('\n', stdout);
115325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
115425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the program header.  */
115725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
115825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
115925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
116003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (phnum == 0)
116125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* No program header, this is OK in relocatable objects.  */
116225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
116325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
116425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (gettext ("Program Headers:"));
116525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
116625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("\
116725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
116825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
116925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (gettext ("\
117025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
117125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
117225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Process all program headers.  */
117325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool has_relro = false;
117425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr relro_from = 0;
117525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr relro_to = 0;
117625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < phnum; ++cnt)
117725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
117825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[128];
117925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr mem;
118025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
118125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
118225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If for some reason the header cannot be returned show this.  */
118325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (phdr == NULL))
118425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
118525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  puts ("  ???");
118625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
118725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
118825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
118925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
119025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
119125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
119225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_offset,
119325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
119425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
119525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_filesz,
119625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_memsz,
119725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_flags & PF_R ? 'R' : ' ',
119825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_flags & PF_W ? 'W' : ' ',
119925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_flags & PF_X ? 'E' : ' ',
120025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_align);
120125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (phdr->p_type == PT_INTERP)
120325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
120403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* If we are sure the file offset is valid then we can show
120503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     the user the name of the interpreter.  We check whether
120603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     there is a section at the file offset.  Normally there
120703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     would be a section called ".interp".  But in separate
120803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     .debug files it is a NOBITS section (and so doesn't match
120903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     with gelf_offscn).  Which probably means the offset is
121003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     not valid another reason could be because the ELF file
121103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     just doesn't contain any section headers, in that case
121203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     just play it safe and don't display anything.  */
121303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
121403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
121503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  GElf_Shdr shdr_mem;
121603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
121703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
121825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t maxsize;
121925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
122025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
122103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
122203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      && filedata != NULL && phdr->p_offset < maxsize
122303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      && phdr->p_filesz <= maxsize - phdr->p_offset
122403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      && memchr (filedata + phdr->p_offset, '\0',
122503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			 phdr->p_filesz) != NULL)
122625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
122725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    filedata + phdr->p_offset);
122825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
122925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (phdr->p_type == PT_GNU_RELRO)
123025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
123125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  has_relro = true;
123225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  relro_from = phdr->p_vaddr;
123325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  relro_to = relro_from + phdr->p_memsz;
123425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
123525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
123625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
123725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_shnum == 0)
123825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* No sections in the file.  Punt.  */
123925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
124025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
124225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
124325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
124425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
124525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
124625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
124825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < phnum; ++cnt)
125025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
125125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Print the segment number.  */
125225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("   %2.2zu     ", cnt);
125325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
125425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr phdr_mem;
125525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
125625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This must not happen.  */
125725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (phdr == NULL))
125825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
125925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_errmsg (-1));
126025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
126125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Iterate over the sections.  */
126225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool in_relro = false;
126325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool in_ro = false;
126425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t inner = 1; inner < shnum; ++inner)
126525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
126625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
126725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This should not happen.  */
126825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (scn == NULL))
126925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
127025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   elf_errmsg (-1));
127125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
127225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Get the section header.  */
127325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr shdr_mem;
127425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
127525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (shdr == NULL))
127625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, 0,
127725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   gettext ("cannot get section header: %s"),
127825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   elf_errmsg (-1));
127925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
128025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_size > 0
128125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Compare allocated sections by VMA, unallocated
128225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 sections by file offset.  */
128325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (shdr->sh_flags & SHF_ALLOC
128425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? (shdr->sh_addr >= phdr->p_vaddr
128525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     && (shdr->sh_addr + shdr->sh_size
128625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 <= phdr->p_vaddr + phdr->p_memsz))
128725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : (shdr->sh_offset >= phdr->p_offset
128825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     && (shdr->sh_offset + shdr->sh_size
128925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 <= phdr->p_offset + phdr->p_filesz))))
129025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
129125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (has_relro && !in_relro
129225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && shdr->sh_addr >= relro_from
129325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && shdr->sh_addr + shdr->sh_size <= relro_to)
129425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
129525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (" [RELRO:", stdout);
129625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  in_relro = true;
129725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
129825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
129925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
130025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked ("]", stdout);
130125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  in_relro =  false;
130225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
130325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (has_relro && in_relro
130425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       && shdr->sh_addr + shdr->sh_size > relro_to)
130525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		fputs_unlocked ("] <RELRO:", stdout);
130625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
130725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
130825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (!in_ro)
130925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
131025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      fputs_unlocked (" [RO:", stdout);
131125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      in_ro = true;
131225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
131325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
131425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
131525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
131625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Determine the segment this section is part of.  */
131725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t cnt2;
131825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Phdr *phdr2 = NULL;
131925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  for (cnt2 = 0; cnt2 < phnum; ++cnt2)
132025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
132125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      GElf_Phdr phdr2_mem;
132225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
132325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
132425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
132525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  && shdr->sh_addr >= phdr2->p_vaddr
132625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  && (shdr->sh_addr + shdr->sh_size
132725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      <= phdr2->p_vaddr + phdr2->p_memsz))
132825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			break;
132925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
133025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (cnt2 < phnum)
133225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
133325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
133425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
133525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  fputs_unlocked (" [RO:", stdout);
133625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  in_ro = true;
133725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
133825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
133925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
134025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  fputs_unlocked ("]", stdout);
134125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  in_ro = false;
134225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
134325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
134425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
134525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (" %s",
134725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
134825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Signal that this sectin is only partially covered.  */
135025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (has_relro && in_relro
135125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       && shdr->sh_addr + shdr->sh_size > relro_to)
135225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
135325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (">", stdout);
135425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  in_relro =  false;
135525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
135625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
135725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
135825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (in_relro || in_ro)
135925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked ("]", stdout);
136025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Finish the line.  */
136225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputc_unlocked ('\n', stdout);
136325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
136425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
136525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
136825b3c049e70834cf33790a28643ab058b507b35cBen Chengsection_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
136925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
137025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
137125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
137225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
137525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
137625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
137725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
137825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
137925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
138125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr symshdr_mem;
138225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
138325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
138425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
138625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || symdata == NULL)
138725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
138825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
139025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
139125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
139225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
139325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
139425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
139625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Sym sym_mem;
139803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
139903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
140025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf ((grpref[0] & GRP_COMDAT)
140125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? ngettext ("\
140225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
140325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      "\
140425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
140525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      data->d_size / sizeof (Elf32_Word) - 1)
140625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : ngettext ("\
140725b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
140825b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
140925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      data->d_size / sizeof (Elf32_Word) - 1),
141025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn),
141125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
141203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  (sym == NULL ? NULL
141303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
141425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: gettext ("<INVALID SYMBOL>"),
141525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data->d_size / sizeof (Elf32_Word) - 1);
141625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
141725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
141825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
141925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr grpshdr_mem;
142025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
142125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 &grpshdr_mem);
142225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
142325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *str;
142425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  [%2u] %s\n",
142525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      grpref[cnt],
142625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      grpshdr != NULL
142725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
142825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ? str : gettext ("<INVALID SECTION>"));
142925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
143025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
143125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
143225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
143325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
143425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_scngrp (Ebl *ebl)
143525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
143625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find all relocation sections and handle them.  */
143725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
143825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
143925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
144025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
144125b3c049e70834cf33790a28643ab058b507b35cBen Cheng       /* Handle the section if it is a symbol table.  */
144225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
144325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
144425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
144525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == SHT_GROUP)
144625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	handle_scngrp (ebl, scn, shdr);
144725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
144825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
144925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
145025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
145125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags
145225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
145325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int mask;
145425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *str;
145525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} dt_flags[] =
145625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
145725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_ORIGIN, "ORIGIN" },
145825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_SYMBOLIC, "SYMBOLIC" },
145925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_TEXTREL, "TEXTREL" },
146025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_BIND_NOW, "BIND_NOW" },
146125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_STATIC_TLS, "STATIC_TLS" }
146225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
146325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
146425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags dt_flags_1[] =
146625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
146725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NOW, "NOW" },
146825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_GLOBAL, "GLOBAL" },
146925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_GROUP, "GROUP" },
147025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NODELETE, "NODELETE" },
147125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_LOADFLTR, "LOADFLTR" },
147225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_INITFIRST, "INITFIRST" },
147325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NOOPEN, "NOOPEN" },
147425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_ORIGIN, "ORIGIN" },
147525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_DIRECT, "DIRECT" },
147625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_TRANS, "TRANS" },
147725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_INTERPOSE, "INTERPOSE" },
147825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NODEFLIB, "NODEFLIB" },
147925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_NODUMP, "NODUMP" },
148025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_CONFALT, "CONFALT" },
148125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_ENDFILTEE, "ENDFILTEE" },
148225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_DISPRELDNE, "DISPRELDNE" },
148325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_1_DISPRELPND, "DISPRELPND" },
148425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
148525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
148625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
148725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags dt_feature_1[] =
148825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
148925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DTF_1_PARINIT, "PARINIT" },
149025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DTF_1_CONFEXP, "CONFEXP" }
149125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
149225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_feature_1 = (sizeof (dt_feature_1)
149325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  / sizeof (dt_feature_1[0]));
149425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
149525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct flags dt_posflag_1[] =
149625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
149725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_P1_LAZYLOAD, "LAZYLOAD" },
149825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    { DF_P1_GROUPPERM, "GROUPPERM" }
149925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
150025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const int ndt_posflag_1 = (sizeof (dt_posflag_1)
150125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  / sizeof (dt_posflag_1[0]));
150225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
150525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_flags (int class, GElf_Xword d_val, const struct flags *flags,
150625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		int nflags)
150725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
150825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool first = true;
150925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int cnt;
151025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
151125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (cnt = 0; cnt < nflags; ++cnt)
151225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (d_val & flags[cnt].mask)
151325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
151425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (!first)
151525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar_unlocked (' ');
151625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fputs_unlocked (flags[cnt].str, stdout);
151725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	d_val &= ~flags[cnt].mask;
151825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	first = false;
151925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
152025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
152125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (d_val != 0)
152225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
152325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!first)
152425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	putchar_unlocked (' ');
152525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
152625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
152725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
152825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  putchar_unlocked ('\n');
152925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
153025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
153325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_flags (int class, GElf_Xword d_val)
153425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
153525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_flags, ndt_flags);
153625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
153725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
154025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_flags_1 (int class, GElf_Xword d_val)
154125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
154225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_flags_1, ndt_flags_1);
154325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
154425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
154725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_feature_1 (int class, GElf_Xword d_val)
154825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
154925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_feature_1, ndt_feature_1);
155025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
155125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
155225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
155325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
155425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dt_posflag_1 (int class, GElf_Xword d_val)
155525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
155625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
155725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
155825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
155925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
156025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
156125b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
156225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
156325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
156403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr glink_mem;
156503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr *glink;
156625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data;
156725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cnt;
156825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
156903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t sh_entsize;
157025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
157125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
157225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  data = elf_getdata (scn, NULL);
157325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
157425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
157525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
157625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
157725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
157825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
157925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
158025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
158103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
158203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
158303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
158403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (glink == NULL)
158503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
158603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   elf_ndxscn (scn));
158703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
158825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
158925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
159025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
159125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
159203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    shdr->sh_size / sh_entsize),
159303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  (unsigned long int) (shdr->sh_size / sh_entsize),
159425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
159525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
159625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (int) shdr->sh_link,
159703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
159825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("  Type              Value\n"), stdout);
159925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
160003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
160125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
160225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Dyn dynmem;
160325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
160425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dyn == NULL)
160525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
160625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
160725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[64];
160825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  %-17s ",
160925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
161025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
161125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (dyn->d_tag)
161225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
161325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_NULL:
161425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_DEBUG:
161525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_BIND_NOW:
161625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_TEXTREL:
161725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* No further output.  */
161825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputc_unlocked ('\n', stdout);
161925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
162025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
162125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_NEEDED:
162225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Shared library: [%s]\n"),
162325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
162425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
162525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
162625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SONAME:
162725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Library soname: [%s]\n"),
162825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
162925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
163025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
163125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RPATH:
163225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Library rpath: [%s]\n"),
163325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
163425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
163525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
163625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RUNPATH:
163725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Library runpath: [%s]\n"),
163825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
163925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
164025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
164125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_PLTRELSZ:
164225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELASZ:
164325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_STRSZ:
164425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELSZ:
164525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELAENT:
164625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SYMENT:
164725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELENT:
164825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_PLTPADSZ:
164925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_MOVEENT:
165025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_MOVESZ:
165125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_INIT_ARRAYSZ:
165225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FINI_ARRAYSZ:
165325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SYMINSZ:
165425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_SYMINENT:
165525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_GNU_CONFLICTSZ:
165625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_GNU_LIBLISTSZ:
165725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
165825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
165925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
166025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_VERDEFNUM:
166125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_VERNEEDNUM:
166225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELACOUNT:
166325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_RELCOUNT:
166425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
166525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
166625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
166725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_PLTREL:;
166825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
166925b3c049e70834cf33790a28643ab058b507b35cBen Cheng						      NULL, 0);
167025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  puts (tagname ?: "???");
167125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
167225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
167325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FLAGS:
167425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_flags (class, dyn->d_un.d_val);
167525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
167625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
167725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FLAGS_1:
167825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_flags_1 (class, dyn->d_un.d_val);
167925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
168025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
168125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_FEATURE_1:
168225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_feature_1 (class, dyn->d_un.d_val);
168325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
168425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
168525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DT_POSFLAG_1:
168625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_dt_posflag_1 (class, dyn->d_un.d_val);
168725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
168825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
168925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
169025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%#0*" PRIx64 "\n",
169125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
169225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
169325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
169425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
169525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
169625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
169725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
169825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the dynamic segment.  */
169925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
170025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_dynamic (Ebl *ebl)
170125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
170225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < phnum; ++i)
170325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
170425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr phdr_mem;
170525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
170625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
170725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
170825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
170925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
171025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr shdr_mem;
171125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
171225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
171325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_dynamic (ebl, scn, shdr);
171425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
171525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
171625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
171725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
171825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
171925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
172025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print relocations.  */
172125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
172225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
172325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
172425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find all relocation sections and handle them.  */
172525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
172625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
172725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
172825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
172925b3c049e70834cf33790a28643ab058b507b35cBen Cheng       /* Handle the section if it is a symbol table.  */
173025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
173125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
173225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
173325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (shdr != NULL))
173425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
173525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_REL)
173625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_relocs_rel (ebl, ehdr, scn, shdr);
173725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_RELA)
173825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_relocs_rela (ebl, ehdr, scn, shdr);
173925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
174025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
174125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
174225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
174325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
174425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle a relocation section.  */
174525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
174625b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
174725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
174825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
174903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
175003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int nentries = shdr->sh_size / sh_entsize;
175125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
175225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
175325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
175425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
175525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
175625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
175725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the symbol table information.  */
175825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
175925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr symshdr_mem;
176025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
176125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
176225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
176325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header of the section the relocations are for.  */
176425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr destshdr_mem;
176525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
176625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &destshdr_mem);
176725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
176825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
176925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
177025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
177125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_offset);
177225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
177325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
177425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
177525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Search for the optional extended section index table.  */
177625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndxdata = NULL;
177725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int xndxscnidx = elf_scnshndx (scn);
177825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (xndxscnidx > 0))
177925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
178025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
178125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
178225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
178325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
178425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
178525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
178625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
178725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_info != 0)
178825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (ngettext ("\
178925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
179025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
179125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
179225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      nentries),
179325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn),
179425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
179525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    (unsigned int) shdr->sh_info,
179625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
179725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    shdr->sh_offset,
179825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    nentries);
179925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
180025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* The .rel.dyn section does not refer to a specific section but
180125b3c049e70834cf33790a28643ab058b507b35cBen Cheng       instead of section index zero.  Do not try to print a section
180225b3c049e70834cf33790a28643ab058b507b35cBen Cheng       name.  */
180325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (ngettext ("\
180425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
180525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
180625b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
180725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      nentries),
180825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    (unsigned int) elf_ndxscn (scn),
180925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
181025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    shdr->sh_offset,
181125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    nentries);
181225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (class == ELFCLASS32
181325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? gettext ("\
181425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset      Type                 Value       Name\n")
181525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : gettext ("\
181625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset              Type                 Value               Name\n"),
181725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 stdout);
181825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
181925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int is_statically_linked = 0;
182025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = 0; cnt < nentries; ++cnt)
182125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
182225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rel relmem;
182325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
182425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (rel != NULL))
182525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
182625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char buf[128];
182725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym symmem;
182825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf32_Word xndx;
182925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
183025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    GELF_R_SYM (rel->r_info),
183125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &symmem, &xndx);
183225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (sym == NULL))
183325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
183425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* As a special case we have to handle relocations in static
183525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 executables.  This only happens for IRELATIVE relocations
183625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 (so far).  There is no symbol table.  */
183725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked == 0)
183825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
183925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Find the program header and look for a PT_INTERP entry. */
184025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_statically_linked = -1;
184125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (ehdr->e_type == ET_EXEC)
184225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
184325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      is_statically_linked = 1;
184425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
184525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      for (size_t inner = 0; inner < phnum; ++inner)
184625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
184725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr phdr_mem;
184825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
184925b3c049e70834cf33790a28643ab058b507b35cBen Cheng							  &phdr_mem);
185025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  if (phdr != NULL && phdr->p_type == PT_INTERP)
185125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    {
185225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      is_statically_linked = -1;
185325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
185425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    }
185525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
185625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
185725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
185825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
185925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked > 0 && shdr->sh_link == 0)
186025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("\
186125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-20s %*s  %s\n",
186225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
186325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
186425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
186525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
186625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
186725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
186825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
186925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, "",
187025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
187125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
187225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
187325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
187425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
187525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
187625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
187725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
187825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
187925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
188025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SYMBOL"),
188125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) GELF_R_SYM (rel->r_info));
188225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
188325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
188425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
188525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
188625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    likely (ebl_reloc_type_check (ebl,
188725b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  GELF_R_TYPE (rel->r_info)))
188825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Avoid the leading R_ which isn't carrying any
188925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       information.  */
189025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
189125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   buf, sizeof (buf)) + 2
189225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    : gettext ("<INVALID RELOC>"),
189325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
189425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
189525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
189625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
189703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      /* This is a relocation against a STT_SECTION symbol.  */
189803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      GElf_Shdr secshdr_mem;
189903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      GElf_Shdr *secshdr;
190003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
190103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						  sym->st_shndx == SHN_XINDEX
190203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						  ? xndx : sym->st_shndx),
190303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				      &secshdr_mem);
190403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
190503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (unlikely (secshdr == NULL))
190625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
190725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
190825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
190925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
191025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
191125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
191225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
191325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
191425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SECTION"),
191525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) (sym->st_shndx == SHN_XINDEX
191625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    ? xndx : sym->st_shndx));
191725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
191825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
191925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
192025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
192125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
192225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
192325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
192425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
192525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
192625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, sym->st_value,
192703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
192825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
192925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
193025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
193125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
193225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
193325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
193425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle a relocation section.  */
193525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
193625b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
193725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
193825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
193903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
194003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int nentries = shdr->sh_size / sh_entsize;
194125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
194225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
194325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
194425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
194525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
194625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
194725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the symbol table information.  */
194825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
194925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr symshdr_mem;
195025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
195125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
195225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
195325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header of the section the relocations are for.  */
195425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr destshdr_mem;
195525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
195625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &destshdr_mem);
195725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
195825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
195925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
196025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
196125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_offset);
196225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
196325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
196425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
196525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Search for the optional extended section index table.  */
196625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndxdata = NULL;
196725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int xndxscnidx = elf_scnshndx (scn);
196825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (xndxscnidx > 0))
196925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
197025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
197125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
197225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
197325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
197425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
197525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
197625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
197703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (shdr->sh_info != 0)
197803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    printf (ngettext ("\
197925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
198025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
198125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
198225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    nentries),
198325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn),
198425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
198525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_info,
198625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
198725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
198825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  nentries);
198903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  else
199003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    /* The .rela.dyn section does not refer to a specific section but
199103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       instead of section index zero.  Do not try to print a section
199203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       name.  */
199303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    printf (ngettext ("\
199403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
199503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    "\
199603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
199703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      nentries),
199803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    (unsigned int) elf_ndxscn (scn),
199903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
200003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    shdr->sh_offset,
200103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    nentries);
200225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (class == ELFCLASS32
200325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? gettext ("\
200425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset      Type            Value       Addend Name\n")
200525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : gettext ("\
200625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Offset              Type            Value               Addend Name\n"),
200725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  stdout);
200825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
200925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int is_statically_linked = 0;
201025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = 0; cnt < nentries; ++cnt)
201125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
201225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rela relmem;
201325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
201425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (rel != NULL))
201525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
201625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char buf[64];
201725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym symmem;
201825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf32_Word xndx;
201925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
202025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    GELF_R_SYM (rel->r_info),
202125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &symmem, &xndx);
202225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
202325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (sym == NULL))
202425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
202525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* As a special case we have to handle relocations in static
202625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 executables.  This only happens for IRELATIVE relocations
202725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 (so far).  There is no symbol table.  */
202825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked == 0)
202925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
203025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Find the program header and look for a PT_INTERP entry. */
203125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_statically_linked = -1;
203225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (ehdr->e_type == ET_EXEC)
203325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
203425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      is_statically_linked = 1;
203525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
203625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      for (size_t inner = 0; inner < phnum; ++inner)
203725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
203825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr phdr_mem;
203925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
204025b3c049e70834cf33790a28643ab058b507b35cBen Cheng							  &phdr_mem);
204125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  if (phdr != NULL && phdr->p_type == PT_INTERP)
204225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    {
204325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      is_statically_linked = -1;
204425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
204525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    }
204625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
204725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
204825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
204925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
205025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_statically_linked > 0 && shdr->sh_link == 0)
205125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("\
205225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
205325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
205425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
205525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
205625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
205725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
205825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
205925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
206025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, "",
206125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			rel->r_addend,
206225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
206325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
206425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
206525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
206625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
206725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
206825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
206925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
207025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
207125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
207225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SYMBOL"),
207325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) GELF_R_SYM (rel->r_info));
207425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
207525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
207625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("\
207725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
207825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
207925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    likely (ebl_reloc_type_check (ebl,
208025b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  GELF_R_TYPE (rel->r_info)))
208125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Avoid the leading R_ which isn't carrying any
208225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       information.  */
208325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
208425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   buf, sizeof (buf)) + 2
208525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    : gettext ("<INVALID RELOC>"),
208625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
208725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    rel->r_addend,
208825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
208925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
209025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
209103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      /* This is a relocation against a STT_SECTION symbol.  */
209203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      GElf_Shdr secshdr_mem;
209303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      GElf_Shdr *secshdr;
209403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
209503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						  sym->st_shndx == SHN_XINDEX
209603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						  ? xndx : sym->st_shndx),
209703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				      &secshdr_mem);
209803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
209903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (unlikely (secshdr == NULL))
210025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
210125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
210225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
210325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
210425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
210525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
210625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
210725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
210825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			gettext ("INVALID SECTION"),
210925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(long int) (sym->st_shndx == SHN_XINDEX
211025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    ? xndx : sym->st_shndx));
211125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
211225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("\
211325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
211425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
211525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
211625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Avoid the leading R_ which isn't carrying any
211725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   information.  */
211825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
211925b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       buf, sizeof (buf)) + 2
212025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: gettext ("<INVALID RELOC>"),
212125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			class == ELFCLASS32 ? 10 : 18, sym->st_value,
212225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			rel->r_addend,
212303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
212425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
212525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
212625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
212725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
212825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
212925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
213025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the program header.  */
213125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
213225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_symtab (Ebl *ebl, int type)
213325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
213425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the symbol table(s).  For this we have to search through the
213525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     section table.  */
213625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
213725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
213825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
213925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
214025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the section if it is a symbol table.  */
214125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
214225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
214325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
214425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
214525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	handle_symtab (ebl, scn, shdr);
214625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
214725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
214825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
214925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
215025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
215125b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
215225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
215325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *versym_data = NULL;
215425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *verneed_data = NULL;
215525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *verdef_data = NULL;
215625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndx_data = NULL;
215725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
215825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word verneed_stridx = 0;
215925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word verdef_stridx = 0;
216025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
216125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
216225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
216325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
216425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
216525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
216625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find out whether we have other sections we might need.  */
216725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *runscn = NULL;
216825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
216925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
217025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr runshdr_mem;
217125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
217225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
217325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (runshdr != NULL))
217425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
217525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (runshdr->sh_type == SHT_GNU_versym
217625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && runshdr->sh_link == elf_ndxscn (scn))
217725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Bingo, found the version information.  Now get the data.  */
217825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    versym_data = elf_getdata (runscn, NULL);
217925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (runshdr->sh_type == SHT_GNU_verneed)
218025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
218125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is the information about the needed versions.  */
218225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verneed_data = elf_getdata (runscn, NULL);
218325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verneed_stridx = runshdr->sh_link;
218425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
218525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (runshdr->sh_type == SHT_GNU_verdef)
218625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
218725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is the information about the defined versions.  */
218825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verdef_data = elf_getdata (runscn, NULL);
218925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      verdef_stridx = runshdr->sh_link;
219025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
219125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
219225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && runshdr->sh_link == elf_ndxscn (scn))
219325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Extended section index.  */
219425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    xndx_data = elf_getdata (runscn, NULL);
219525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
219625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
219725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
219825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
219925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
220025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
220125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
220225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
220325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
220403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr glink_mem;
220503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
220603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				   &glink_mem);
220703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (glink == NULL)
220803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
220903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   elf_ndxscn (scn));
221003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
221125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now we can compute the number of entries in the section.  */
221225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int nsyms = data->d_size / (class == ELFCLASS32
221325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       ? sizeof (Elf32_Sym)
221425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       : sizeof (Elf64_Sym));
221525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
221625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
221725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
221825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    nsyms),
221925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
222025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
222125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
222225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    " %lu local symbols  String table: [%2u] '%s'\n",
222325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_info),
222425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned long int) shdr->sh_info,
222525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
222603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
222725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
222825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (class == ELFCLASS32
222925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? gettext ("\
223025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
223125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  : gettext ("\
223225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
223325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  stdout);
223425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
223525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
223625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
223725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char typebuf[64];
223825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char bindbuf[64];
223925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char scnbuf[64];
224025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf32_Word xndx;
224125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Sym sym_mem;
224225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
224325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
224425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (sym == NULL))
224525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
224625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
224725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Determine the real section index.  */
224825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (sym->st_shndx != SHN_XINDEX))
224925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	xndx = sym->st_shndx;
225025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
225125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
225225b3c049e70834cf33790a28643ab058b507b35cBen Cheng%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
225325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cnt,
225425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      class == ELFCLASS32 ? 8 : 16,
225525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      sym->st_value,
225625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      sym->st_size,
225725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
225825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    typebuf, sizeof (typebuf)),
225925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
226025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       bindbuf, sizeof (bindbuf)),
226125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
226225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
226325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				sizeof (scnbuf), NULL, shnum),
226425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
226525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
226625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (versym_data != NULL)
226725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
226825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Get the version information.  */
226925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Versym versym_mem;
227025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
227125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
227225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
227325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
227425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bool is_nobits = false;
227525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bool check_def = xndx != SHN_UNDEF;
227625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
227725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
227825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
227925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Shdr symshdr_mem;
228025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Shdr *symshdr =
228125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
228225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
228325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_nobits = (symshdr != NULL
228425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       && symshdr->sh_type == SHT_NOBITS);
228525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
228625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
228725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (is_nobits || ! check_def)
228825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
228925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* We must test both.  */
229025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux vernaux_mem;
229125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux *vernaux = NULL;
229225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t vn_offset = 0;
229325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
229425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verneed verneed_mem;
229525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
229625b3c049e70834cf33790a28643ab058b507b35cBen Cheng							   &verneed_mem);
229725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (verneed != NULL)
229825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
229925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      size_t vna_offset = vn_offset;
230025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
230125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      vernaux = gelf_getvernaux (verneed_data,
230225b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 vna_offset += verneed->vn_aux,
230325b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 &vernaux_mem);
230425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      while (vernaux != NULL
230525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     && vernaux->vna_other != *versym
230625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     && vernaux->vna_next != 0)
230725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
230825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* Update the offset.  */
230925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  vna_offset += vernaux->vna_next;
231025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
231125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  vernaux = (vernaux->vna_next == 0
231225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     ? NULL
231325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     : gelf_getvernaux (verneed_data,
231425b3c049e70834cf33790a28643ab058b507b35cBen Cheng							vna_offset,
231525b3c049e70834cf33790a28643ab058b507b35cBen Cheng							&vernaux_mem));
231625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
231725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
231825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      /* Check whether we found the version.  */
231925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (vernaux != NULL && vernaux->vna_other == *versym)
232025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Found it.  */
232125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			break;
232225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
232325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      vn_offset += verneed->vn_next;
232425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      verneed = (verneed->vn_next == 0
232525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 ? NULL
232625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 : gelf_getverneed (verneed_data, vn_offset,
232725b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    &verneed_mem));
232825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
232925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
233025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (vernaux != NULL && vernaux->vna_other == *versym)
233125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
233225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf ("@%s (%u)",
233325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      elf_strptr (ebl->elf, verneed_stridx,
233425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  vernaux->vna_name),
233525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      (unsigned int) vernaux->vna_other);
233625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      check_def = 0;
233725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
233825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else if (unlikely (! is_nobits))
233925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    error (0, 0, gettext ("bad dynamic symbol"));
234025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
234125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    check_def = 1;
234225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
234325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
234425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (check_def && *versym != 0x8001)
234525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
234625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* We must test both.  */
234725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t vd_offset = 0;
234825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
234925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verdef verdef_mem;
235025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
235125b3c049e70834cf33790a28643ab058b507b35cBen Cheng							&verdef_mem);
235225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (verdef != NULL)
235325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
235425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (verdef->vd_ndx == (*versym & 0x7fff))
235525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			/* Found the definition.  */
235625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			break;
235725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
235825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      vd_offset += verdef->vd_next;
235925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      verdef = (verdef->vd_next == 0
236025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				? NULL
236125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				: gelf_getverdef (verdef_data, vd_offset,
236225b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  &verdef_mem));
236325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
236425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
236525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (verdef != NULL)
236625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
236725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      GElf_Verdaux verdaux_mem;
236825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      GElf_Verdaux *verdaux
236925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			= gelf_getverdaux (verdef_data,
237025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   vd_offset + verdef->vd_aux,
237125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   &verdaux_mem);
237225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
237325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (verdaux != NULL)
237425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
237525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				elf_strptr (ebl->elf, verdef_stridx,
237625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    verdaux->vda_name));
237725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
237825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
237925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
238025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
238125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
238225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar_unlocked ('\n');
238325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
238425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
238525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
238625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
238725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print version information.  */
238825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
238925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_verinfo (Ebl *ebl)
239025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
239125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the version information sections.  For this we have to
239225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     search through the section table.  */
239325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
239425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
239525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
239625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
239725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the section if it is part of the versioning handling.  */
239825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
239925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
240025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
240125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (shdr != NULL))
240225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
240325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_GNU_verneed)
240425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_verneed (ebl, scn, shdr);
240525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_GNU_verdef)
240625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_verdef (ebl, scn, shdr);
240725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_GNU_versym)
240825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_versym (ebl, scn, shdr);
240925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
241025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
241125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
241225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
241325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
241425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
241525b3c049e70834cf33790a28643ab058b507b35cBen Chengget_ver_flags (unsigned int flags)
241625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
241725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static char buf[32];
241825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *endp;
241925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
242025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (flags == 0)
242125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return gettext ("none");
242225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
242325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (flags & VER_FLG_BASE)
242425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    endp = stpcpy (buf, "BASE ");
242525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
242625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    endp = buf;
242725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
242825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (flags & VER_FLG_WEAK)
242925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
243025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp != buf)
243125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	endp = stpcpy (endp, "| ");
243225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
243325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      endp = stpcpy (endp, "WEAK ");
243425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
243525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
243625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
243725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
243825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
243925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      buf[sizeof (buf) - 1] = '\0';
244025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
244125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
244225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return buf;
244325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
244425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
244525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
244625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
244725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
244825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
244925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
245025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
245125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
245225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
245325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
245425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
245525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
245625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
245725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
245825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
245925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
246025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
246125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
246203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr glink_mem;
246303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
246403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				   &glink_mem);
246503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (glink == NULL)
246603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
246703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   elf_ndxscn (scn));
246803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
246925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
247025b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
247125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
247225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
247325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_info),
247425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
247525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
247625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
247725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
247825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
247903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
248025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
248125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int offset = 0;
248225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = shdr->sh_info; --cnt >= 0; )
248325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
248425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the data at the next offset.  */
248525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verneed needmem;
248625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
248725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (need == NULL))
248825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
248925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
249025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
249125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset, (unsigned short int) need->vn_version,
249225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
249325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (unsigned short int) need->vn_cnt);
249425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
249525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int auxoffset = offset + need->vn_aux;
249625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
249725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
249825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Vernaux auxmem;
249925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
250025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (aux == NULL))
250125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
250225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
250325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
250425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset,
250525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
250625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  get_ver_flags (aux->vna_flags),
250725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (unsigned short int) aux->vna_other);
250825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
250903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (aux->vna_next == 0)
251003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    break;
251103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
251225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  auxoffset += aux->vna_next;
251325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
251425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
251525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Find the next offset.  */
251603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (need->vn_next == 0)
251703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	break;
251803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
251925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += need->vn_next;
252025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
252125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
252225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
252325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
252425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
252525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
252625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
252725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
252825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
252925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
253025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
253125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
253225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
253325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
253425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
253525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
253625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
253725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
253803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr glink_mem;
253903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
254003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				   &glink_mem);
254103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (glink == NULL)
254203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
254303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   elf_ndxscn (scn));
254403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
254525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
254625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
254725b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
254825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
254925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
255025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_info),
255125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
255225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
255325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_info,
255425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
255525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
255625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
255703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
255825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
255925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int offset = 0;
256025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = shdr->sh_info; --cnt >= 0; )
256125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
256225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the data at the next offset.  */
256325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdef defmem;
256425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
256525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (def == NULL))
256625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
256725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
256825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int auxoffset = offset + def->vd_aux;
256925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdaux auxmem;
257025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
257125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (aux == NULL))
257225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
257325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
257425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
257525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
257625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset, def->vd_version,
257725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      get_ver_flags (def->vd_flags),
257825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      def->vd_ndx,
257925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      def->vd_cnt,
258025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
258125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
258225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      auxoffset += aux->vda_next;
258325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
258425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
258525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
258625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (aux == NULL))
258725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
258825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
258925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("  %#06x: Parent %d: %s\n"),
259025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset, cnt2,
259125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
259225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
259303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (aux->vda_next == 0)
259403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    break;
259503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
259625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  auxoffset += aux->vda_next;
259725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
259825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
259925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Find the next offset.  */
260003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (def->vd_next == 0)
260103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	break;
260225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += def->vd_next;
260325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
260425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
260525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
260625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
260725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
260825b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
260925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
261025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int class = gelf_getclass (ebl->elf);
261125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char **vername;
261225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char **filename;
261325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
261425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the data of the section.  */
261525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
261625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
261725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
261825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
261925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
262025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
262125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
262225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
262325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
262425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
262525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We have to find the version definition section and extract the
262625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     version names.  */
262725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *defscn = NULL;
262825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *needscn = NULL;
262925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
263025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *verscn = NULL;
263125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
263225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
263325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr vershdr_mem;
263425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
263525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
263625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (vershdr != NULL))
263725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
263825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (vershdr->sh_type == SHT_GNU_verdef)
263925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    defscn = verscn;
264025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (vershdr->sh_type == SHT_GNU_verneed)
264125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    needscn = verscn;
264225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
264325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
264425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
264525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nvername;
264625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (defscn != NULL || needscn != NULL)
264725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
264825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We have a version information (better should have).  Now get
264925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 the version names.  First find the maximum version number.  */
265025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      nvername = 0;
265125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (defscn != NULL)
265225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
265325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Run through the version definitions and find the highest
265425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     index.  */
265525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
265625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *defdata;
265725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr defshdrmem;
265825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *defshdr;
265925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
266025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defdata = elf_getdata (defscn, NULL);
266125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defdata == NULL))
266225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
266325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
266425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defshdr = gelf_getshdr (defscn, &defshdrmem);
266525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defshdr == NULL))
266625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
266725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
266825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
266925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
267025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef defmem;
267125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef *def;
267225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
267325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
267425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      def = gelf_getverdef (defdata, offset, &defmem);
267525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (def == NULL))
267625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
267725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
267825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
267925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
268003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (def->vd_next == 0)
268103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		break;
268225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += def->vd_next;
268325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
268425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
268525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (needscn != NULL)
268625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
268725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
268825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *needdata;
268925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr needshdrmem;
269025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *needshdr;
269125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
269225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  needdata = elf_getdata (needscn, NULL);
269325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (needdata == NULL))
269425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
269525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
269625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  needshdr = gelf_getshdr (needscn, &needshdrmem);
269725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (needshdr == NULL))
269825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
269925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
270025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
270125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
270225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed needmem;
270325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed *need;
270425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int auxoffset;
270525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int cnt2;
270625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
270725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
270825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      need = gelf_getverneed (needdata, offset, &needmem);
270925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (need == NULL))
271025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
271125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
271225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Run through the auxiliary entries.  */
271325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      auxoffset = offset + need->vn_aux;
271425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
271525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
271625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux auxmem;
271725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux *aux;
271825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
271925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
272025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (aux == NULL))
272125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    break;
272225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
272325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  nvername = MAX (nvername,
272425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  (size_t) (aux->vna_other & 0x7fff));
272525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
272603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  if (aux->vna_next == 0)
272703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    break;
272825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset += aux->vna_next;
272925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
273025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
273103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (need->vn_next == 0)
273203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		break;
273325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += need->vn_next;
273425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
273525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
273625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
273725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is the number of versions we know about.  */
273825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++nvername;
273925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
274025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Allocate the array.  */
274125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      vername = (const char **) alloca (nvername * sizeof (const char *));
274203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      memset(vername, 0, nvername * sizeof (const char *));
274325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      filename = (const char **) alloca (nvername * sizeof (const char *));
274403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      memset(filename, 0, nvername * sizeof (const char *));
274525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
274625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Run through the data structures again and collect the strings.  */
274725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (defscn != NULL)
274825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
274925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Run through the version definitions and find the highest
275025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     index.  */
275125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
275225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *defdata;
275325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr defshdrmem;
275425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *defshdr;
275525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
275625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defdata = elf_getdata (defscn, NULL);
275725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defdata == NULL))
275825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
275925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
276025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  defshdr = gelf_getshdr (defscn, &defshdrmem);
276125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (defshdr == NULL))
276225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
276325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
276425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
276525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
276625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
276725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
276825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef defmem;
276925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
277003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (unlikely (def == NULL))
277103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		break;
277203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
277325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdaux auxmem;
277425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
277525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   offset + def->vd_aux,
277625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   &auxmem);
277703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (unlikely (aux == NULL))
277825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
277925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
278025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      vername[def->vd_ndx & 0x7fff]
278125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
278225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      filename[def->vd_ndx & 0x7fff] = NULL;
278325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
278403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (def->vd_next == 0)
278503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		break;
278625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += def->vd_next;
278725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
278825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
278925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (needscn != NULL)
279025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
279125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int offset = 0;
279225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
279325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *needdata = elf_getdata (needscn, NULL);
279425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr needshdrmem;
279525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
279625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (needdata == NULL || needshdr == NULL))
279725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
279825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
279925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
280025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
280125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Get the data at the next offset.  */
280225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed needmem;
280325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
280425b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    &needmem);
280525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (need == NULL))
280625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
280725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
280825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Run through the auxiliary entries.  */
280925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int auxoffset = offset + need->vn_aux;
281025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
281125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
281225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux auxmem;
281325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
281425b3c049e70834cf33790a28643ab058b507b35cBen Cheng						       &auxmem);
281525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (aux == NULL))
281625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    break;
281725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
281825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  vername[aux->vna_other & 0x7fff]
281925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
282025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  filename[aux->vna_other & 0x7fff]
282125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
282225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
282303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  if (aux->vna_next == 0)
282403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    break;
282525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  auxoffset += aux->vna_next;
282625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
282725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
282803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (need->vn_next == 0)
282903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		break;
283025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset += need->vn_next;
283125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
283225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
283325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
283425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
283525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
283625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      vername = NULL;
283725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      nvername = 1;
283825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      filename = NULL;
283925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
284025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
284103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr glink_mem;
284203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
284303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				   &glink_mem);
284403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
284503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (glink == NULL)
284603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"),
284703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   elf_ndxscn (scn));
284803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
284925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Print the header.  */
285025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
285125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
285225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
285325b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
285403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    shdr->sh_size / sh_entsize),
285525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
285625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
285703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  (int) (shdr->sh_size / sh_entsize),
285825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
285925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
286025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
286103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
286225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
286325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now we can finally look at the actual contents of this section.  */
286403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
286525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
286625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cnt % 2 == 0)
286725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("\n %4d:", cnt);
286825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
286925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Versym symmem;
287025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
287125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (sym == NULL)
287225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
287325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
287425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (*sym)
287525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
287625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ssize_t n;
287725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 0:
287825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (gettext ("   0 *local*                     "),
287925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  stdout);
288025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
288125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
288225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 1:
288325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fputs_unlocked (gettext ("   1 *global*                    "),
288425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  stdout);
288525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
288625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
288725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
288825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  n = printf ("%4d%c%s",
288925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
289003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      (vername != NULL
289103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		       && (unsigned int) (*sym & 0x7fff) < nvername)
289225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      ? vername[*sym & 0x7fff] : "???");
289325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((unsigned int) (*sym & 0x7fff) < nvername
289403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      && filename != NULL && filename[*sym & 0x7fff] != NULL)
289525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    n += printf ("(%s)", filename[*sym & 0x7fff]);
289625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s", MAX (0, 33 - (int) n), " ");
289725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
289825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
289925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
290025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  putchar_unlocked ('\n');
290125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
290225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
290325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
290425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
290525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
290625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 uint_fast32_t maxlength, Elf32_Word nbucket,
290725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
290825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
290925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
291025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
291125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
291225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ++counts[lengths[cnt]];
291325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
291403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr glink_mem;
291503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
291603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					       shdr->sh_link),
291703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				   &glink_mem);
291803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (glink == NULL)
291903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
292003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("invalid sh_link value in section %Zu"),
292103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     elf_ndxscn (scn));
292203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
292303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
292403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
292525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
292625b3c049e70834cf33790a28643ab058b507b35cBen 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",
292725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
292825b3c049e70834cf33790a28643ab058b507b35cBen 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",
292925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    nbucket),
293025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) elf_ndxscn (scn),
293125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
293225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (int) nbucket,
293325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
293425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_addr,
293525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_offset,
293625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (unsigned int) shdr->sh_link,
293703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
293825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
293925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (extrastr != NULL)
294025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    fputs (extrastr, stdout);
294125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
294225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (nbucket > 0))
294325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
294425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t success = 0;
294525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
294625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* xgettext:no-c-format */
294725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs_unlocked (gettext ("\
294825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Length  Number  % of total  Coverage\n"), stdout);
294925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
295025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      counts[0], (counts[0] * 100.0) / nbucket);
295125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
295225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t nzero_counts = 0;
295325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
295425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
295525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  nzero_counts += counts[cnt] * cnt;
295625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\
295725b3c049e70834cf33790a28643ab058b507b35cBen Cheng%7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
295825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
295925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (nzero_counts * 100.0) / nsyms);
296025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
296125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
296225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf32_Word acc = 0;
296325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
296425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
296525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  acc += cnt;
296625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  success += counts[cnt] * acc;
296725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
296825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
296925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
297025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Average number of tests:   successful lookup: %f\n\
297125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  unsuccessful lookup: %f\n"),
297225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (double) success / (double) nzero_counts,
297325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (double) nzero_counts / (double) nbucket);
297425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
297525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
297625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (counts);
297725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
297825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
297925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
298025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This function handles the traditional System V-style hash table format.  */
298125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
298225b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
298325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
298425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
298525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
298625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
298725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
298825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
298925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
299025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
299125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
299203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
299303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
299403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    invalid_data:
299503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("invalid data in sysv.hash section %d"),
299603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     (int) elf_ndxscn (scn));
299703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
299803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
299903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
300025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
300125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
300203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
300303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
300403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (used_buf > data->d_size)
300503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    goto invalid_data;
300603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
300725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
300825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
300925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
301025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
301125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
301225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t maxlength = 0;
301325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nsyms = 0;
301425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
301525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
301625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf32_Word inner = bucket[cnt];
301725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (inner > 0 && inner < nchain)
301825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
301925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++nsyms;
302025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (maxlength < ++lengths[cnt])
302125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++maxlength;
302225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
302325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  inner = chain[inner];
302425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
302525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
302625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
302725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
302825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   lengths, NULL);
302925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
303025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (lengths);
303125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
303225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
303325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
303425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This function handles the incorrect, System V-style hash table
303525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   format some 64-bit architectures use.  */
303625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
303725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
303825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
303925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
304025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
304125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
304225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
304325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
304425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
304525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
304625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
304703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
304803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
304903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    invalid_data:
305003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
305103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     (int) elf_ndxscn (scn));
305203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
305303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
305403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
305525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
305625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
305703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
305803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
305903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (maxwords < 2
306003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      || maxwords - 2 < nbucket
306103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      || maxwords - 2 - nbucket < nchain)
306203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    goto invalid_data;
306303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
306425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
306525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
306625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
306725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
306825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
306925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t maxlength = 0;
307025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nsyms = 0;
307125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
307225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
307325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf64_Xword inner = bucket[cnt];
307425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (inner > 0 && inner < nchain)
307525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
307625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++nsyms;
307725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (maxlength < ++lengths[cnt])
307825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++maxlength;
307925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
308025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  inner = chain[inner];
308125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
308225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
308325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
308425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
308525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   lengths, NULL);
308625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
308725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (lengths);
308825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
308925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
309025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
309125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This function handles the GNU-style hash table format.  */
309225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
309325b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
309425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
309525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata (scn, NULL);
309625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
309725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
309825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
309925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
310025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
310125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
310225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
310303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
310403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
310503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    invalid_data:
310603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("invalid data in gnu.hash section %d"),
310703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     (int) elf_ndxscn (scn));
310803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
310903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
311003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
311125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
311225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
311325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
311425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Next comes the size of the bitmap.  It's measured in words for
311525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
311603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     64 bit archs.  There is always a bloom filter present, so zero is
311703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     an invalid value.  */
311825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
311925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (gelf_getclass (ebl->elf) == ELFCLASS64)
312025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    bitmask_words *= 2;
312125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
312203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (bitmask_words == 0)
312303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    goto invalid_data;
312403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
312525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
312625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
312703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Is there still room for the sym chain?
312803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     Use uint64_t calculation to prevent 32bit overlow.  */
312903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
313003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
313103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (used_buf > data->d_size)
313203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    goto invalid_data;
313303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
313425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
313525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
313625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
313725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
313825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
313925b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    + nbucket];
314025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
314125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Compute distribution of chain lengths.  */
314225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t maxlength = 0;
314325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nsyms = 0;
314425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
314525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (bucket[cnt] != 0)
314625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
314725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	Elf32_Word inner = bucket[cnt] - symbias;
314825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	do
314925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
315025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++nsyms;
315125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (maxlength < ++lengths[cnt])
315225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ++maxlength;
315303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if (inner > max_nsyms)
315403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid_data;
315525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
315625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	while ((chain[inner++] & 1) == 0);
315725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
315825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
315925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Count bits in bitmask.  */
316025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast32_t nbits = 0;
316125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
316225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
316325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast32_t word = bitmask[cnt];
316425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
316525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
316625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
316725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
316825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
316925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
317025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
317125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
317225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *str;
317325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (asprintf (&str, gettext ("\
317425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Symbol Bias: %u\n\
317525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
317625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (unsigned int) symbias,
317725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  bitmask_words * sizeof (Elf32_Word),
317825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  ((nbits * 100 + 50)
317925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   / (uint_fast32_t) (bitmask_words
318025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      * sizeof (Elf32_Word) * 8)),
318125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (unsigned int) shift) == -1))
318225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
318325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
318425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
318525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   lengths, str);
318625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
318725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (str);
318825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (lengths);
318925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
319025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
319125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
319225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Find the symbol table(s).  For this we have to search through the
319325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   section table.  */
319425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
319525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_hash (Ebl *ebl)
319625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
319725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
319825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
319925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
320025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
320125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
320225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
320325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
320425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
320525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
320625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the section if it is a symbol table.  */
320725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
320825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
320925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
321025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (shdr != NULL))
321125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
321225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type == SHT_HASH)
321325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
321425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
321525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
321625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
321725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_sysv_hash (ebl, scn, shdr, shstrndx);
321825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
321925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (shdr->sh_type == SHT_GNU_HASH)
322025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
322125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
322225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
322325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
322425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
322525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
322625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
322725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_liblist (Ebl *ebl)
322825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
322925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the library list sections.  For this we have to search
323025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     through the section table.  */
323125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
323225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
323325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
323425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
323525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
323625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
323725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
323825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
323925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
324025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
324125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
324225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
324325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
324425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
324525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
324603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
324703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  int nentries = shdr->sh_size / sh_entsize;
324825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (ngettext ("\
324925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
325025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    "\
325125b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
325225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    nentries),
325325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn),
325425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
325525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_offset,
325625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  nentries);
325725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
325825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Data *data = elf_getdata (scn, NULL);
325925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (data == NULL)
326025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return;
326125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
326225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  puts (gettext ("\
326325b3c049e70834cf33790a28643ab058b507b35cBen Cheng       Library                       Time Stamp          Checksum Version Flags"));
326425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
326525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (int cnt = 0; cnt < nentries; ++cnt)
326625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
326725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Lib lib_mem;
326825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
326925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (lib == NULL))
327025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
327125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
327225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      time_t t = (time_t) lib->l_time_stamp;
327325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct tm *tm = gmtime (&t);
327425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (tm == NULL))
327525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
327625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
327725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
327825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
327925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
328025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      tm->tm_hour, tm->tm_min, tm->tm_sec,
328125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (unsigned int) lib->l_checksum,
328225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (unsigned int) lib->l_version,
328325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (unsigned int) lib->l_flags);
328425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
328525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
328625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
328725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
328825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
328925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
329025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
329125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
329225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Find the object attributes sections.  For this we have to search
329325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     through the section table.  */
329425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
329525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
329625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
329725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
329825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
329925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
330025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
330125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
330225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
330325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
330425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
330525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
330625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
330725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
330825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   && (shdr->sh_type != SHT_ARM_ATTRIBUTES
330925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       || ehdr->e_machine != EM_ARM)))
331025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
331125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
331225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
331325b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nObject attributes section [%2zu] '%s' of %" PRIu64
331425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " bytes at offset %#0" PRIx64 ":\n"),
331525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_ndxscn (scn),
331625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
331725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      shdr->sh_size, shdr->sh_offset);
331825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
331925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
332003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (data == NULL || data->d_size == 0))
332125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return;
332225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
332325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *p = data->d_buf;
332425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
332503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* There is only one 'version', A.  */
332625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (*p++ != 'A'))
332725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return;
332825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
332925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
333025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
333125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      inline size_t left (void)
333225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
333325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return (const unsigned char *) data->d_buf + data->d_size - p;
333425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
333525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
333603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* Loop over the sections.  */
333725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (left () >= 4)
333825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
333903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* Section length.  */
334025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint32_t len;
334125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (&len, p, sizeof len);
334225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
334325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
334425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (len);
334525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
334625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (len > left ()))
334725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
334825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
334903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* Section vendor name.  */
335025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *name = p + sizeof len;
335125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  p += len;
335225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
335325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned const char *q = memchr (name, '\0', len);
335425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (q == NULL))
335503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    break;
335625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++q;
335725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
335825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
335925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
336003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  bool gnu_vendor = (q - name == sizeof "gnu"
336103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			     && !memcmp (name, "gnu", sizeof "gnu"));
336203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
336303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* Loop over subsections.  */
336425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr->sh_type != SHT_GNU_ATTRIBUTES
336503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      || gnu_vendor)
336625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (q < p)
336725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
336825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		const unsigned char *const sub = q;
336925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
337025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		unsigned int subsection_tag;
337103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		get_uleb128 (subsection_tag, q, p);
337225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (q >= p))
337325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
337425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
337525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		uint32_t subsection_len;
337625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
337725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
337825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
337925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		memcpy (&subsection_len, q, sizeof subsection_len);
338025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
338125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
338225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  CONVERT (subsection_len);
338325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
338403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		/* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
338503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		if (unlikely (subsection_len == 0
338603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			      || subsection_len >= (uint32_t) PTRDIFF_MAX
338703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			      || p - sub < (ptrdiff_t) subsection_len))
338825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
338925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
339025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		const unsigned char *r = q + sizeof subsection_len;
339125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		q = sub + subsection_len;
339225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
339325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		switch (subsection_tag)
339425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
339525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  default:
339603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    /* Unknown subsection, print and skip.  */
339725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("    %-4u %12" PRIu32 "\n"),
339825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    subsection_tag, subsection_len);
339925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    break;
340025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
340125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  case 1:	/* Tag_File */
340225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("    File: %11" PRIu32 "\n"),
340325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    subsection_len);
340425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
340525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    while (r < q)
340625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      {
340725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			unsigned int tag;
340803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			get_uleb128 (tag, r, q);
340925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (unlikely (r >= q))
341025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  break;
341125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
341203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			/* GNU style tags have either a uleb128 value,
341303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   when lowest bit is not set, or a string
341403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   when the lowest bit is set.
341503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   "compatibility" (32) is special.  It has
341603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   both a string and a uleb128 value.  For
341703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   non-gnu we assume 6 till 31 only take ints.
341803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   XXX see arm backend, do we need a separate
341903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   hook?  */
342025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			uint64_t value = 0;
342125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const char *string = NULL;
342203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			if (tag == 32 || (tag & 1) == 0
342303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    || (! gnu_vendor && (tag > 5 && tag < 32)))
342425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
342503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    get_uleb128 (value, r, q);
342625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (r > q)
342725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
342825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
342903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			if (tag == 32
343003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    || ((tag & 1) != 0
343103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				&& (gnu_vendor
343203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				    || (! gnu_vendor && tag > 32)))
343303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    || (! gnu_vendor && tag > 3 && tag < 6))
343425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
343503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    string = (const char *) r;
343625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    r = memchr (r, '\0', q - r);
343725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (r == NULL)
343825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      break;
343925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    ++r;
344025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
344125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
344225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const char *tag_name = NULL;
344325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const char *value_name = NULL;
344425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			ebl_check_object_attribute (ebl, (const char *) name,
344525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    tag, value,
344625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    &tag_name, &value_name);
344725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
344825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			if (tag_name != NULL)
344925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
345025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (tag == 32)
345125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %s: %" PRId64 ", %s\n"),
345225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag_name, value, string);
345325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    else if (string == NULL && value_name == NULL)
345425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %s: %" PRId64 "\n"),
345525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag_name, value);
345625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    else
345725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %s: %s\n"),
345825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag_name, string ?: value_name);
345925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
346025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			else
346125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  {
346203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    /* For "gnu" vendor 32 "compatibility" has
346303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			       already been handled above.  */
346403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    assert (tag != 32
346503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				    || strcmp ((const char *) name, "gnu"));
346625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    if (string == NULL)
346725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %u: %" PRId64 "\n"),
346825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag, value);
346925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    else
347025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      printf (gettext ("      %u: %s\n"),
347125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      tag, string);
347225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  }
347325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      }
347425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
347525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
347625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
347725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
347825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
347925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
348025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
348125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic char *
348225b3c049e70834cf33790a28643ab058b507b35cBen Chengformat_dwarf_addr (Dwfl_Module *dwflmod,
348303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   int address_size, Dwarf_Addr address, Dwarf_Addr raw)
348425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
348525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* See if there is a name we can give for this address.  */
348625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Sym sym;
348703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Off off = 0;
348803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *name = (print_address_names && ! print_unresolved_addresses)
348903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
349003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    : NULL;
349125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
349203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *scn;
349303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (print_unresolved_addresses)
349403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
349503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      address = raw;
349603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      scn = NULL;
349703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
349803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  else
349903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
350003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* Relativize the address.  */
350103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      int n = dwfl_module_relocations (dwflmod);
350203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
350325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
350403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* In an ET_REL file there is a section name to refer to.  */
350503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      scn = (i < 0 ? NULL
350603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     : dwfl_module_relocation_info (dwflmod, i, NULL));
350703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
350825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
350925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *result;
351025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((name != NULL
351103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       ? (off != 0
351225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? (scn != NULL
351325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? (address_size == 0
351425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
351525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
351603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    scn, address, name, off)
351725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
351825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
351925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    scn, 2 + address_size * 2, address,
352003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    name, off))
352125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : (address_size == 0
352225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
352325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
352403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    address, name, off)
352525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
352625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
352725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    2 + address_size * 2, address,
352803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    name, off)))
352925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : (scn != NULL
353025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? (address_size == 0
353125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
353225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#" PRIx64 " <%s>"),
353325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    scn, address, name)
353425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
353525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%s+%#0*" PRIx64 " <%s>"),
353625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    scn, 2 + address_size * 2, address, name))
353725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : (address_size == 0
353825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? asprintf (&result,
353925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#" PRIx64 " <%s>"),
354025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    address, name)
354125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: asprintf (&result,
354225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    gettext ("%#0*" PRIx64 " <%s>"),
354325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    2 + address_size * 2, address, name))))
354425b3c049e70834cf33790a28643ab058b507b35cBen Cheng       : (scn != NULL
354525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ? (address_size == 0
354625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? asprintf (&result,
354725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 gettext ("%s+%#" PRIx64),
354825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 scn, address)
354925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : asprintf (&result,
355025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 gettext ("%s+%#0*" PRIx64),
355125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 scn, 2 + address_size * 2, address))
355225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  : (address_size == 0
355325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ? asprintf (&result,
355425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 "%#" PRIx64,
355525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 address)
355625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     : asprintf (&result,
355725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 "%#0*" PRIx64,
355825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 2 + address_size * 2, address)))) < 0)
355925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0, _("memory exhausted"));
356025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
356125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
356225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
356325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
356425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
356525b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_tag_string (unsigned int tag)
356625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
356703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  switch (tag)
356803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
356903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
357003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_TAG
357103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_TAG
357203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    default:
357303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return NULL;
357403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
357503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
357625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
357725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
357803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
357903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_attr_string (unsigned int attrnum)
358003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
358103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  switch (attrnum)
358203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
358303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
358403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_AT
358503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_AT
358603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    default:
358703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return NULL;
358803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
358903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
359025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
359125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
359203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
359303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_form_string (unsigned int form)
359403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
359503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  switch (form)
359603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
359703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_FORM_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_FORM (NAME, CODE)
359803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
359903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_FORM
360003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_FORM
360103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_FORM_DESC
360203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    default:
360303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return NULL;
360403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
360503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
360625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
360725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
360803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
360903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_lang_string (unsigned int lang)
361003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
361103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  switch (lang)
361203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
361303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_LANG_DESC(NAME, CODE, DESC) case CODE: return #NAME;
361403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_LANG
361503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_LANG_DESC
361603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    default:
361703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return NULL;
361803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
361903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
362025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
362125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
362203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
362303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_inline_string (unsigned int code)
362403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
362503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  static const char *const known[] =
362603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
362703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
362803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_INL
362903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_INL
363003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    };
363125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
363203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (code < sizeof (known) / sizeof (known[0])))
363303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known[code];
363425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
363503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
363603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
363725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
363825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
363903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
364003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_encoding_string (unsigned int code)
364103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
364203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  static const char *const known[] =
364303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
364403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
364503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_ATE
364603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_ATE
364703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    };
364825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
364903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (code < sizeof (known) / sizeof (known[0])))
365003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known[code];
365125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
365203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
365325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
365425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
365525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
365625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
365703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_access_string (unsigned int code)
365825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
365903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  static const char *const known[] =
366003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
366103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
366203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_ACCESS
366303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_ACCESS
366425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
366525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
366603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (code < sizeof (known) / sizeof (known[0])))
366703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known[code];
366825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
366903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
367003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
367125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
367225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
367303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
367403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_visibility_string (unsigned int code)
367503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
367603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  static const char *const known[] =
367703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
367803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
367903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_VIS
368003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_VIS
368103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    };
368225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
368303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (code < sizeof (known) / sizeof (known[0])))
368403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known[code];
368525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
368603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
368703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
368825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
368925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
369003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
369103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_virtuality_string (unsigned int code)
369203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
369303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  static const char *const known[] =
369403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
369503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
369603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_VIRTUALITY
369703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_VIRTUALITY
369803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    };
369925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
370003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (code < sizeof (known) / sizeof (known[0])))
370103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known[code];
370225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
370303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
370425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
370525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
370625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
370725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
370803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_identifier_case_string (unsigned int code)
370925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
371003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  static const char *const known[] =
371103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
371203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
371303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_ID
371403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_ID
371525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
371625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
371703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (code < sizeof (known) / sizeof (known[0])))
371803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known[code];
371925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
372003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
372125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
372225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
372325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
372425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
372503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_calling_convention_string (unsigned int code)
372625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
372725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
372825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
372903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
373003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_CC
373103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_CC
373225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
373325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
373403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (code < sizeof (known) / sizeof (known[0])))
373503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known[code];
373625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
373703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
373825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
373925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
374025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
374125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
374203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_ordering_string (unsigned int code)
374325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
374425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
374525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
374603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
374703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_ORD
374803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_ORD
374925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
375025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
375125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
375225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
375325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
375403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
375525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
375625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
375725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
375825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
375903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_discr_list_string (unsigned int code)
376025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
376125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
376225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
376303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
376403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_DSC
376503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_DSC
376625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
376725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
376825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
376925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
377025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
377103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
377225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
377325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
377425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
377525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
377603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_locexpr_opcode_string (unsigned int code)
377725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
377825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  static const char *const known[] =
377925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
378003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* Normally we can't affort building huge table of 64K entries,
378103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 most of them zero, just because there are a couple defined
378203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 values at the far end.  In case of opcodes, it's OK.  */
378303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE)
378403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
378503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ALL_KNOWN_DW_OP
378603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_OP
378703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef ONE_KNOWN_DW_OP_DESC
378825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
378925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
379125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return known[code];
379225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
379425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
379525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
379703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Used by all dwarf_foo_name functions.  */
379825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
379903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstring_or_unknown (const char *known, unsigned int code,
380003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes                   unsigned int lo_user, unsigned int hi_user,
380103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   bool print_unknown_num)
380225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
380303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  static char unknown_buf[20];
380403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
380503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (likely (known != NULL))
380603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return known;
380703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
380803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (lo_user != 0 && code >= lo_user && code <= hi_user)
380925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
381003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
381103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		code - lo_user);
381203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return unknown_buf;
381303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
381425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
381503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (print_unknown_num)
381603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
381703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
381803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return unknown_buf;
381903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
382025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
382125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return "???";
382225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
382325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
382425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
382525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
382603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_tag_name (unsigned int tag)
382725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
382803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_tag_string (tag);
382903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
383003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
383125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
383203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
383303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_attr_name (unsigned int attr)
383403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
383503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_attr_string (attr);
383603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
383703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
383825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
383903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
384003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
384103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_form_name (unsigned int form)
384203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
384303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_form_string (form);
384403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, form, 0, 0, true);
384525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
384625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
384725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
384825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
384903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_lang_name (unsigned int lang)
385025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
385103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_lang_string (lang);
385203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
385303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
385425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
385525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
385603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
385703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_inline_name (unsigned int code)
385803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
385903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_inline_string (code);
386003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, 0, 0, false);
386125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
386225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
386325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
386425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
386503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_encoding_name (unsigned int code)
386625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
386703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_encoding_string (code);
386803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
386903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
387025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
387125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
387203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
387303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_access_name (unsigned int code)
387403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
387503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_access_string (code);
387603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, 0, 0, false);
387703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
387825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
387903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
388003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
388103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_visibility_name (unsigned int code)
388203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
388303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_visibility_string (code);
388403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, 0, 0, false);
388525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
388625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
388725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
388825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
388903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_virtuality_name (unsigned int code)
389025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
389103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_virtuality_string (code);
389203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, 0, 0, false);
389303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
389425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
389525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
389603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
389703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_identifier_case_name (unsigned int code)
389803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
389903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_identifier_case_string (code);
390003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, 0, 0, false);
390125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
390225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
390325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
390425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
390503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_calling_convention_name (unsigned int code)
390625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
390703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_calling_convention_string (code);
390803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
390903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
391025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
391125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
391203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
391303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_ordering_name (unsigned int code)
391403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
391503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_ordering_string (code);
391603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, 0, 0, false);
391703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
391803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
391903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
392003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *
392103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_discr_list_name (unsigned int code)
392203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
392303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const char *ret = dwarf_discr_list_string (code);
392403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return string_or_unknown (ret, code, 0, 0, false);
392525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
392625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
392725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
392825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
392925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_block (size_t n, const void *block)
393025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
393125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (n == 0)
393225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts (_("empty block"));
393325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
393425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
393525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (_("%zu byte block:"), n);
393625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *data = block;
393725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
393825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (" %02x", *data++);
393925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (--n > 0);
394025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar ('\n');
394125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
394225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
394325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
394425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
394525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
394625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   unsigned int vers, unsigned int addrsize, unsigned int offset_size,
394703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
394825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
394925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
395025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
395125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (len == 0)
395225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
395325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%*s(empty)\n", indent, "");
395425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
395525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
395625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
395725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define NEED(n)		if (len < (Dwarf_Word) (n)) goto invalid
395825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define CONSUME(n)	NEED (n); else len -= (n)
395925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
396025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word offset = 0;
396125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (len-- > 0)
396225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
396325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t op = *data++;
396425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
396503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const char *op_name = dwarf_locexpr_opcode_string (op);
396603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (op_name == NULL))
396703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
396803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  static char buf[20];
396903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (op >= DW_OP_lo_user)
397003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
397103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else
397203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    snprintf (buf, sizeof buf, "??? (%#x)", op);
397303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  op_name = buf;
397403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
397503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
397625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (op)
397725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
397825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_addr:;
397925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Address operand.  */
398025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Word addr;
398125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (addrsize);
398225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (addrsize == 4)
398325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    addr = read_4ubyte_unaligned (dbg, data);
398403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else if (addrsize == 8)
398503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    addr = read_8ubyte_unaligned (dbg, data);
398625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
398703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid;
398825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += addrsize;
398925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (addrsize);
399025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
399103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *a = format_dwarf_addr (dwflmod, 0, addr, addr);
399225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %s\n",
399303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, a);
399425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (a);
399525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
399625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + addrsize;
399725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
399825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
399925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call_ref:
400025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Offset operand.  */
400103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (ref_size != 4 && ref_size != 8)
400203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid; /* Cannot be used in CFA.  */
400325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (ref_size);
400425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ref_size == 4)
400525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    addr = read_4ubyte_unaligned (dbg, data);
400625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
400703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    addr = read_8ubyte_unaligned (dbg, data);
400825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += ref_size;
400925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (ref_size);
401025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
401125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
401225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
401303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, (uintmax_t) addr);
401425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + ref_size;
401525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
401625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
401725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_deref_size:
401825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_xderef_size:
401925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_pick:
402025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const1u:
402125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
402225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
402325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
402425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
402503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, *((uint8_t *) data));
402625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++data;
402725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  --len;
402825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 2;
402925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
403025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
403125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const2u:
403225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
403325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
403425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
403525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
403603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, read_2ubyte_unaligned (dbg, data));
403725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
403825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 2;
403925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
404025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
404125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
404225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const4u:
404325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (4);
404425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
404525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
404625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
404703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, read_4ubyte_unaligned (dbg, data));
404825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (4);
404925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 4;
405025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 5;
405125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
405225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
405325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const8u:
405425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (8);
405525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
405625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
405725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
405803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
405925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (8);
406025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 8;
406125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 9;
406225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
406325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
406425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const1s:
406525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
406625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
406725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
406825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
406903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, *((int8_t *) data));
407025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++data;
407125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  --len;
407225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 2;
407325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
407425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
407525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const2s:
407625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
407725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
407825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
407925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
408003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, read_2sbyte_unaligned (dbg, data));
408125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
408225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 2;
408325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
408425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
408525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
408625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const4s:
408725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (4);
408825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
408925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
409025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
409103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, read_4sbyte_unaligned (dbg, data));
409225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (4);
409325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 4;
409425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 5;
409525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
409625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
409725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_const8s:
409825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (8);
409925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX value might be modified by relocation
410025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
410125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
410203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, read_8sbyte_unaligned (dbg, data));
410325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (8);
410425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 8;
410525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 9;
410625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
410725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
410825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_piece:
410925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_regx:
411025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_plus_uconst:
411125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_constu:;
411225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *start = data;
411325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t uleb;
411425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
411503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
411625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
411703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, uleb);
411825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
411925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
412025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
412125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
412225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bit_piece:
412325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
412425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t uleb2;
412503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
412603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
412703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
412803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb2, data, data + len);
412925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
413003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
413125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
413225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
413325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
413425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
413525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_fbreg:
413625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_breg0 ... DW_OP_breg31:
413725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_consts:
413825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
413925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int64_t sleb;
414025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
414103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_sleb128 (sleb, data, data + len);
414225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
414303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, sleb);
414425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
414525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
414625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
414725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
414825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bregx:
414925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
415003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
415103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
415203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
415303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_sleb128 (sleb, data, data + len);
415425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
415503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, uleb, sleb);
415625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
415725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
415825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
415925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
416025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call2:
416125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
416225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
416303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name,
416425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  read_2ubyte_unaligned (dbg, data));
416525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
416625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
416725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
416825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
416925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_call4:
417025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (4);
417125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
417203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name,
417325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  read_4ubyte_unaligned (dbg, data));
417425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (4);
417525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 5;
417625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
417725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
417825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_skip:
417925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_bra:
418025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (2);
418125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
418203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name,
418303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
418425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (2);
418525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += 2;
418625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 3;
418725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
418825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
418925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_implicit_value:
419025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
419125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
419203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
419325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s: ",
419403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name);
419525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (uleb);
419625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_block (uleb, data);
419725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += uleb;
419825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
419925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
420025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
420125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
420225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_implicit_pointer:
420325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* DIE offset operand.  */
420425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
420503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (ref_size);
420603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (ref_size != 4 && ref_size != 8)
420703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid; /* Cannot be used in CFA.  */
420825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ref_size == 4)
420925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    addr = read_4ubyte_unaligned (dbg, data);
421025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
421103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    addr = read_8ubyte_unaligned (dbg, data);
421225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += ref_size;
421325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Byte offset operand.  */
421403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
421503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_sleb128 (sleb, data, data + len);
421625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
421703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
421825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (intmax_t) offset,
421903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, (uintmax_t) addr, sleb);
422025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
422125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
422225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
422325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
422425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_entry_value:
422525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Size plus expression block.  */
422625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
422725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
422803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
422925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s:\n",
423003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name);
423125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (uleb);
423225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
423303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		     addrsize, offset_size, cu, uleb, data);
423425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += uleb;
423525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
423625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
423725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
423825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
423925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_const_type:
424003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
424103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     unsigned size plus block.  */
424225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
424303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
424403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
424503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (! print_unresolved_addresses && cu != NULL)
424603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    uleb += cu->start;
424703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
424825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint8_t usize = *(uint8_t *) data++;
424925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (usize);
425025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
425103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, uleb);
425225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_block (usize, data);
425325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data += usize;
425425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
425525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
425625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
425725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
425825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_regval_type:
425903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* uleb128 register number, uleb128 CU relative
426003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     DW_TAG_base_type DIE offset.  */
426125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
426203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
426303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
426403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
426503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb2, data, data + len);
426603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (! print_unresolved_addresses && cu != NULL)
426703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    uleb2 += cu->start;
426803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
426903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
427025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
427125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
427225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
427325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
427425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_deref_type:
427503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* 1-byte unsigned size of value, uleb128 CU relative
427603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     DW_TAG_base_type DIE offset.  */
427725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
427803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
427925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  usize = *(uint8_t *) data++;
428003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (1);
428103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
428203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (! print_unresolved_addresses && cu != NULL)
428303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    uleb += cu->start;
428425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
428525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  indent, "", (uintmax_t) offset,
428603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  op_name, usize, uleb);
428725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
428825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
428925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
429025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
429125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_convert:
429225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_OP_GNU_reinterpret:
429303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* uleb128 CU relative offset to DW_TAG_base_type, or zero
429403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     for conversion to untyped.  */
429525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = data;
429625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  NEED (1);
429703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (uleb, data, data + len);
429803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
429903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    uleb += cu->start;
430025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
430103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, uleb);
430225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  CONSUME (data - start);
430325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += 1 + (data - start);
430425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
430525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
430603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	case DW_OP_GNU_parameter_ref:
430703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* 4 byte CU relative reference to the abstract optimized away
430803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     DW_TAG_formal_parameter.  */
430903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  NEED (4);
431003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
431103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (! print_unresolved_addresses && cu != NULL)
431203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    param_off += cu->start;
431303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
431403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name, param_off);
431503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  CONSUME (4);
431603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  data += 4;
431703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  offset += 5;
431803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  break;
431903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
432025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
432125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* No Operand.  */
432203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf ("%*s[%4" PRIuMAX "] %s\n",
432303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  indent, "", (uintmax_t) offset, op_name);
432425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++offset;
432525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
432625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
432725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
432825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      indent = indentrest;
432925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      continue;
433025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
433125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid:
433225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("%*s[%4" PRIuMAX "] %s  <TRUNCATED>\n"),
433303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      indent, "", (uintmax_t) offset, op_name);
433425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
433525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
433625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
433725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
433825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
433925b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct listptr
434025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
434125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset:(64 - 3);
434225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool addr64:1;
434325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool dwarf64:1;
434425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool warned:1;
434503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct Dwarf_CU *cu;
434625b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
434725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
434825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define listptr_offset_size(p)	((p)->dwarf64 ? 8 : 4)
434925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define listptr_address_size(p)	((p)->addr64 ? 8 : 4)
435025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
435103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic Dwarf_Addr
435203333823c75a1c1887e923828113a1b0fd12020cElliott Hugheslistptr_base (struct listptr *p)
435303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
435403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Addr base;
435503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Die cu = CUDIE (p->cu);
435603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Find the base address of the compilation unit.  It will normally
435703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     be specified by DW_AT_low_pc.  In DWARF-3 draft 4, the base
435803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     address could be overridden by DW_AT_entry_pc.  It's been
435903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
436003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     compilation units with discontinuous ranges.  */
436103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (unlikely (dwarf_lowpc (&cu, &base) != 0))
436203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
436303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Attribute attr_mem;
436403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwarf_formaddr (dwarf_attr (&cu, DW_AT_entry_pc, &attr_mem),
436503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  &base) != 0)
436603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	base = 0;
436703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
436803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return base;
436903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
437003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
437125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
437225b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_listptr (const void *a, const void *b, void *arg)
437325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
437425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *name = arg;
437525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *p1 = (void *) a;
437625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *p2 = (void *) b;
437725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
437825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (p1->offset < p2->offset)
437925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
438025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (p1->offset > p2->offset)
438125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
438225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
438325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!p1->warned && !p2->warned)
438425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
438525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (p1->addr64 != p2->addr64)
438625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
438725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  p1->warned = p2->warned = true;
438825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0,
438925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 gettext ("%s %#" PRIx64 " used with different address sizes"),
439025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 name, (uint64_t) p1->offset);
439125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
439225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (p1->dwarf64 != p2->dwarf64)
439325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
439425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  p1->warned = p2->warned = true;
439525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0,
439625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 gettext ("%s %#" PRIx64 " used with different offset sizes"),
439725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 name, (uint64_t) p1->offset);
439825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
439903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (listptr_base (p1) != listptr_base (p2))
440003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
440103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  p1->warned = p2->warned = true;
440203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0,
440303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 gettext ("%s %#" PRIx64 " used with different base addresses"),
440403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 name, (uint64_t) p1->offset);
440503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
440625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
440725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
440825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
440925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
441025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
441125b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct listptr_table
441225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
441325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t n;
441425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t alloc;
441525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *table;
441625b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
441725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
441825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct listptr_table known_loclistptr;
441925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct listptr_table known_rangelistptr;
442025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
442125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
442225b3c049e70834cf33790a28643ab058b507b35cBen Chengreset_listptr (struct listptr_table *table)
442325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
442425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (table->table);
442525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  table->table = NULL;
442625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  table->n = table->alloc = 0;
442725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
442825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
442903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Returns false if offset doesn't fit.  See struct listptr.  */
443003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
443125b3c049e70834cf33790a28643ab058b507b35cBen Chengnotice_listptr (enum section_e section, struct listptr_table *table,
443225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		uint_fast8_t address_size, uint_fast8_t offset_size,
443303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		struct Dwarf_CU *cu, Dwarf_Off offset)
443425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
443525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (print_debug_sections & section)
443625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
443725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (table->n == table->alloc)
443825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
443925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (table->alloc == 0)
444025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    table->alloc = 128;
444125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
444225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    table->alloc *= 2;
444325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  table->table = xrealloc (table->table,
444425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   table->alloc * sizeof table->table[0]);
444525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
444625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
444725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct listptr *p = &table->table[table->n++];
444825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
444925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *p = (struct listptr)
445025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
445125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  .addr64 = address_size == 8,
445225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  .dwarf64 = offset_size == 8,
445303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  .offset = offset,
445403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  .cu = cu
445525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	};
445603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
445703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (p->offset != offset)
445803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
445903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  table->n--;
446003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return false;
446103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
446225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
446303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return true;
446425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
446525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
446625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
446725b3c049e70834cf33790a28643ab058b507b35cBen Chengsort_listptr (struct listptr_table *table, const char *name)
446825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
446925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (table->n > 0)
447025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    qsort_r (table->table, table->n, sizeof table->table[0],
447125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     &compare_listptr, (void *) name);
447225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
447325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
447425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool
447525b3c049e70834cf33790a28643ab058b507b35cBen Chengskip_listptr_hole (struct listptr_table *table, size_t *idxp,
447625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
447703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
447803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		   unsigned char **readp, unsigned char *endp)
447925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
448025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (table->n == 0)
448125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
448225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
448325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
448425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ++*idxp;
448525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
448625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct listptr *p = &table->table[*idxp];
448725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
448825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*idxp == table->n
448925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || p->offset >= (Dwarf_Off) (endp - *readp + offset))
449025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
449125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *readp = endp;
449225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext (" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
449325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset);
449425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return true;
449525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
449625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
449725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (p->offset != (Dwarf_Off) offset)
449825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
449925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *readp += p->offset - offset;
450025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext (" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
450125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset, (Dwarf_Off) p->offset - offset);
450225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return true;
450325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
450425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
450525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (address_sizep != NULL)
450625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *address_sizep = listptr_address_size (p);
450725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (offset_sizep != NULL)
450825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *offset_sizep = listptr_offset_size (p);
450903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (base != NULL)
451003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    *base = listptr_base (p);
451103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (cu != NULL)
451203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    *cu = p->cu;
451325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
451425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return false;
451525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
451625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
451725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
451825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
451925b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
452025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Ebl *ebl, GElf_Ehdr *ehdr,
452125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
452225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
452303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
452403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  dbg->sectiondata[IDX_debug_abbrev]->d_size : 0);
452503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
452625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
452725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " [ Code]\n"),
452825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
452925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
453025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
453125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset = 0;
453203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (offset < sh_size)
453325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
453425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
453525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      offset);
453625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
453725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (1)
453825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
453925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t length;
454025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Abbrev abbrev;
454125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
454225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
454325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (res != 0)
454425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
454525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (res < 0))
454625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
454725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext ("\
454825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *** error while reading abbreviation: %s\n"),
454925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  dwarf_errmsg (-1));
455025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  return;
455125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
455225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
455325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is the NUL byte at the end of the section.  */
455425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ++offset;
455525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
455625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
455725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
455825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We know these calls can never fail.  */
455925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int code = dwarf_getabbrevcode (&abbrev);
456025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
456125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int has_children = dwarf_abbrevhaschildren (&abbrev);
456225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
456325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%5u] offset: %" PRId64
456425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   ", children: %s, tag: %s\n"),
456525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  code, (int64_t) offset,
456625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  has_children ? gettext ("yes") : gettext ("no"),
456703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  dwarf_tag_name (tag));
456825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
456925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t cnt = 0;
457025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int name;
457125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int form;
457225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Off enoffset;
457325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (dwarf_getabbrevattr (&abbrev, cnt,
457425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &name, &form, &enoffset) == 0)
457525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
457625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
457703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      dwarf_attr_name (name), dwarf_form_name (form),
457825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (uint64_t) enoffset);
457925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
458025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ++cnt;
458125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
458225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
458325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset += length;
458425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
458525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
458625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
458725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
458825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
458925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print content of DWARF .debug_aranges section.  We fortunately do
459025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   not have to know a bit about the structure of the section, libdwarf
459125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   takes care of it.  */
459225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
459303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
459403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			       GElf_Shdr *shdr, Dwarf *dbg)
459525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
459625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Aranges *aranges;
459725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cnt;
459825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
459925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
460025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
460125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     dwarf_errmsg (-1));
460225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
460325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
460425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
460503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr glink_mem;
460603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Shdr *glink;
460703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
460803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (glink == NULL)
460903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
461003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("invalid sh_link value in section %Zu"),
461103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     elf_ndxscn (scn));
461203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
461303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
461403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
461525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (ngettext ("\
461625b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
461725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\
461825b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
461925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    cnt),
462025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
462125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset, cnt);
462225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
462325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Compute floor(log16(cnt)).  */
462425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t tmp = cnt;
462525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int digits = 1;
462625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (tmp >= 16)
462725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
462825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++digits;
462925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      tmp >>= 4;
463025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
463125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
463225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t n = 0; n < cnt; ++n)
463325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
463425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Arange *runp = dwarf_onearange (aranges, n);
463525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (runp == NULL))
463625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
463725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
463825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return;
463925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
464025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
464125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr start;
464225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word length;
464325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off offset;
464425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
464525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
464625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" [%*zu] ???\n"), digits, n);
464725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
464825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" [%*zu] start: %0#*" PRIx64
464925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", length: %5" PRIu64 ", CU DIE offset: %6"
465025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 PRId64 "\n"),
465125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
465225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) start, (uint64_t) length, (int64_t) offset);
465325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
465425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
465525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
465603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
465703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Print content of DWARF .debug_aranges section.  */
465803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
465903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
466003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			     Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
466103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			     GElf_Shdr *shdr, Dwarf *dbg)
466203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
466303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (decodedaranges)
466403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
466503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
466603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
466703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
466803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
466903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = dbg->sectiondata[IDX_debug_aranges];
467003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
467103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (unlikely (data == NULL))
467203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
467303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
467403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     elf_errmsg (-1));
467503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
467603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
467703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
467803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  printf (gettext ("\
467903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
468003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
468103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  (uint64_t) shdr->sh_offset);
468203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
468303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const unsigned char *readp = data->d_buf;
468403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const unsigned char *readendp = readp + data->d_size;
468503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
468603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (readp < readendp)
468703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
468803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const unsigned char *hdrstart = readp;
468903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
469003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
469103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
469203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp + 4 > readendp)
469303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
469403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	invalid_data:
469503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
469603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
469703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return;
469803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
469903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
470003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
470103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      unsigned int length_bytes = 4;
470203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (length == DWARF3_LENGTH_64_BIT)
470303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
470403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (readp + 8 > readendp)
470503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_data;
470603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  length = read_8ubyte_unaligned_inc (dbg, readp);
470703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  length_bytes = 8;
470803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
470903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
471003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const unsigned char *nexthdr = readp + length;
471103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext ("\n Length:        %6" PRIu64 "\n"),
471203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (uint64_t) length);
471303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
471403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (length > (size_t) (readendp - readp)))
471503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
471603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
471703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (length == 0)
471803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
471903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
472003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp + 2 > readendp)
472103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
472203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
472303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"),
472403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      version);
472503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (version != 2)
472603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
472703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("unsupported aranges version"));
472803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  goto next_table;
472903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
473003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
473103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Word offset;
473203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp + length_bytes > readendp)
473303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
473403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (length_bytes == 8)
473503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	offset = read_8ubyte_unaligned_inc (dbg, readp);
473603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else
473703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	offset = read_4ubyte_unaligned_inc (dbg, readp);
473803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" CU offset:     %6" PRIx64 "\n"),
473903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (uint64_t) offset);
474003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
474103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp + 1 > readendp)
474203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
474303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      unsigned int address_size = *readp++;
474403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" Address size:  %6" PRIu64 "\n"),
474503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (uint64_t) address_size);
474603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (address_size != 4 && address_size != 8)
474703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
474803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("unsupported address size"));
474903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  goto next_table;
475003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
475103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
475203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      unsigned int segment_size = *readp++;
475303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" Segment size:  %6" PRIu64 "\n\n"),
475403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (uint64_t) segment_size);
475503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (segment_size != 0 && segment_size != 4 && segment_size != 8)
475603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
475703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("unsupported segment size"));
475803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  goto next_table;
475903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
476003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
476103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* Round the address to the next multiple of 2*address_size.  */
476203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
476303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		% (2 * address_size));
476403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
476503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      while (readp < nexthdr)
476603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
476703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Word range_address;
476803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Word range_length;
476903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Word segment = 0;
477003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (readp + 2 * address_size + segment_size > readendp)
477103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_data;
477203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (address_size == 4)
477303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
477403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      range_address = read_4ubyte_unaligned_inc (dbg, readp);
477503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      range_length = read_4ubyte_unaligned_inc (dbg, readp);
477603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
477703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else
477803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
477903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      range_address = read_8ubyte_unaligned_inc (dbg, readp);
478003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      range_length = read_8ubyte_unaligned_inc (dbg, readp);
478103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
478203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
478303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (segment_size == 4)
478403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    segment = read_4ubyte_unaligned_inc (dbg, readp);
478503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else if (segment_size == 8)
478603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    segment = read_8ubyte_unaligned_inc (dbg, readp);
478703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
478803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (range_address == 0 && range_length == 0 && segment == 0)
478903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    break;
479003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
479103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *b = format_dwarf_addr (dwflmod, address_size, range_address,
479203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       range_address);
479303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *e = format_dwarf_addr (dwflmod, address_size,
479403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       range_address + range_length - 1,
479503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       range_length);
479603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (segment_size != 0)
479703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    printf (gettext ("   %s..%s (%" PRIx64 ")\n"), b, e,
479803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    (uint64_t) segment);
479903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else
480003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    printf (gettext ("   %s..%s\n"), b, e);
480103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  free (b);
480203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  free (e);
480303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
480403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
480503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    next_table:
480603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp != nexthdr)
480703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
480803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  size_t padding = nexthdr - readp;
480903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf (gettext ("   %Zu padding bytes\n"), padding);
481003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  readp = nexthdr;
481103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
481203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
481303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
481403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
481503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
481625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print content of DWARF .debug_ranges section.  */
481725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
481825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_ranges_section (Dwfl_Module *dwflmod,
481925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Ebl *ebl, GElf_Ehdr *ehdr,
482025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Elf_Scn *scn, GElf_Shdr *shdr,
482125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    Dwarf *dbg)
482225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
482303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = dbg->sectiondata[IDX_debug_ranges];
482425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
482525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
482625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
482725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
482825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
482925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
483025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
483125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
483225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
483325b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
483425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
483525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
483625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
483725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sort_listptr (&known_rangelistptr, "rangelistptr");
483825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t listptr_idx = 0;
483925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
484025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
484125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
484225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool first = true;
484303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Addr base = 0;
484425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
484525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *readp = data->d_buf;
484625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < endp)
484725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
484825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
484925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
485025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
485103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				      &address_size, NULL, &base, NULL,
485225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      offset, &readp, endp))
485325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
485425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
485503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (data->d_size - offset < (size_t) address_size * 2))
485625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
485725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
485825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
485925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
486025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
486125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr begin;
486225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr end;
486325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (address_size == 8)
486425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
486525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_8ubyte_unaligned_inc (dbg, readp);
486625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_8ubyte_unaligned_inc (dbg, readp);
486725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
486825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
486925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
487025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_4ubyte_unaligned_inc (dbg, readp);
487125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_4ubyte_unaligned_inc (dbg, readp);
487225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (begin == (Dwarf_Addr) (uint32_t) -1)
487325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    begin = (Dwarf_Addr) -1l;
487425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
487525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
487625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
487725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
487803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *b = format_dwarf_addr (dwflmod, address_size, end, end);
487925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
488025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
488103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  base = end;
488225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
488325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (begin == 0 && end == 0) /* End of list entry.  */
488425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
488525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)
488625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  empty list\n"), offset);
488725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = true;
488825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
488925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
489025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
489103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
489203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       begin);
489303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *e = format_dwarf_addr (dwflmod, address_size, base + end,
489403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       end);
489525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We have an address range entry.  */
489625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)		/* First address range entry in a list.  */
489725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  %s..%s\n"), offset, b, e);
489825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
489925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext ("           %s..%s\n"), b, e);
490025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
490125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (e);
490225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
490325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = false;
490425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
490525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
490625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
490725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
490825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define REGNAMESZ 16
490925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
491025b3c049e70834cf33790a28643ab058b507b35cBen Chengregister_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
491125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       char name[REGNAMESZ], int *bits, int *type)
491225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
491325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *set;
491425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *pfx;
491525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int ignore;
491625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
491725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 bits ?: &ignore, type ?: &ignore);
491825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (n <= 0)
491925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
492003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (loc != NULL)
492103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	snprintf (name, REGNAMESZ, "reg%u", loc->regno);
492203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else
492303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	snprintf (name, REGNAMESZ, "??? 0x%x", regno);
492425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (bits != NULL)
492503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	*bits = loc != NULL ? loc->bits : 0;
492625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (type != NULL)
492725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*type = DW_ATE_unsigned;
492825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      set = "??? unrecognized";
492925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
493025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
493125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
493225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (bits != NULL && *bits <= 0)
493303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	*bits = loc != NULL ? loc->bits : 0;
493425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (type != NULL && *type == DW_ATE_void)
493525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*type = DW_ATE_unsigned;
493625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
493725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
493825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return set;
493925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
494025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
494125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
494225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_cfa_program (const unsigned char *readp, const unsigned char *const endp,
494325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Dwarf_Word vma_base, unsigned int code_align,
494425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   int data_align,
494525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   unsigned int version, unsigned int ptr_size,
494625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
494725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
494825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char regnamebuf[REGNAMESZ];
494925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *regname (unsigned int regno)
495025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
495125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
495225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return regnamebuf;
495325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
495425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
495525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts ("\n   Program:");
495625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Word pc = vma_base;
495725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < endp)
495825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
495925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int opcode = *readp++;
496025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
496125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (opcode < DW_CFA_advance_loc)
496225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Extended opcode.  */
496325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	switch (opcode)
496425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
496525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    uint64_t op1;
496625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    int64_t sop1;
496725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    uint64_t op2;
496825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    int64_t sop2;
496925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
497025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_nop:
497125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     nop");
497225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
497325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_set_loc:
497403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
497503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
497603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
497725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 += vma_base;
497825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     set_loc %" PRIu64 "\n", op1 * code_align);
497925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
498025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_advance_loc1:
498103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
498203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
498325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     advance_loc1 %u to %#" PRIx64 "\n",
498425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    *readp, pc += *readp * code_align);
498525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ++readp;
498625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
498725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_advance_loc2:
498803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 2)
498903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
499025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 = read_2ubyte_unaligned_inc (dbg, readp);
499125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
499225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, pc += op1 * code_align);
499325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
499425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_advance_loc4:
499503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 4)
499603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
499725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 = read_4ubyte_unaligned_inc (dbg, readp);
499825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
499925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, pc += op1 * code_align);
500025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
500125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_offset_extended:
500203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
500303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
500403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
500503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
500603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
500703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op2, readp, endp);
500825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
500925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "\n",
501025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), op2 * data_align);
501125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
501225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_restore_extended:
501303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
501403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
501503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
501625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
501725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
501825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
501925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_undefined:
502003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
502103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
502203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
502325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
502425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
502525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_same_value:
502603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
502703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
502803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
502925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
503025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
503125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_register:
503203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
503303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
503403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
503503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
503603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
503703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op2, readp, endp);
503825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
503925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), op2, regname (op2));
504025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
504125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_remember_state:
504225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     remember_state");
504325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
504425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_restore_state:
504525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     restore_state");
504625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
504725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa:
504803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
504903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
505003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
505103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
505203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
505303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op2, readp, endp);
505425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
505525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), op2);
505625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
505725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_register:
505803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
505903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
506003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
506125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
506225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
506325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
506425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_offset:
506503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
506603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
506703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
506825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
506925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
507025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_expression:
507103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
507203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
507303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);	/* Length of DW_FORM_block.  */
507425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
507503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < op1)
507603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      {
507703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    invalid:
507803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	        fputs (gettext ("         <INVALID DATA>\n"), stdout);
507903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		return;
508003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      }
508103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
508203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		       op1, readp);
508325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += op1;
508425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
508525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_expression:
508603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
508703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
508803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
508903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
509003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
509103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
509225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     expression r%" PRIu64 " (%s) \n",
509325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
509403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < op2)
509503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
509603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
509703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		       op2, readp);
509825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += op2;
509925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
510025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_offset_extended_sf:
510103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
510203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
510303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
510403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
510503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
510603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_sleb128 (sop2, readp, endp);
510725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
510825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    PRId64 "\n",
510925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), sop2 * data_align);
511025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
511125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_sf:
511203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
511303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
511403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
511503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
511603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
511703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_sleb128 (sop2, readp, endp);
511825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
511925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1), sop2 * data_align);
512025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
512125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_def_cfa_offset_sf:
512203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
512303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
512403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_sleb128 (sop1, readp, endp);
512525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
512625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
512725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_val_offset:
512803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
512903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
513003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
513103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
513203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
513303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op2, readp, endp);
513425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
513525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, op2 * data_align);
513625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
513725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_val_offset_sf:
513803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
513903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
514003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
514103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
514203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
514303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_sleb128 (sop2, readp, endp);
514425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
514525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, sop2 * data_align);
514625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
514725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_val_expression:
514803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
514903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
515003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
515103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
515203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
515303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
515425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     val_expression r%" PRIu64 " (%s)\n",
515525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, regname (op1));
515603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < op2)
515703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
515803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
515903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		       NULL, op2, readp);
516025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += op2;
516125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
516225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_MIPS_advance_loc8:
516303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 8)
516403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
516525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    op1 = read_8ubyte_unaligned_inc (dbg, readp);
516625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
516725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    op1, pc += op1 * code_align);
516825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
516925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_GNU_window_save:
517025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts ("     GNU_window_save");
517125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
517225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case DW_CFA_GNU_args_size:
517303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if ((uint64_t) (endp - readp) < 1)
517403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto invalid;
517503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (op1, readp, endp);
517625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     args_size %" PRIu64 "\n", op1);
517725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
517825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  default:
517925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("     ??? (%u)\n", opcode);
518025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
518125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
518225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (opcode < DW_CFA_offset)
518325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("     advance_loc %u to %#" PRIx64 "\n",
518425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
518525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (opcode < DW_CFA_restore)
518625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
518725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t offset;
518803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if ((uint64_t) (endp - readp) < 1)
518903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid;
519003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (offset, readp, endp);
519125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
519225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
519325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
519425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
519525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("     restore r%u (%s)\n",
519625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		opcode & 0x3f, regname (opcode & 0x3f));
519725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
519825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
519925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
520025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
520125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
520225b3c049e70834cf33790a28643ab058b507b35cBen Chengencoded_ptr_size (int encoding, unsigned int ptr_size)
520325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
520425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (encoding & 7)
520525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
520603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case DW_EH_PE_udata4:
520725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 4;
520803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case DW_EH_PE_udata8:
520925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 8;
521003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case 0:
521125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ptr_size;
521225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
521303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
521403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  fprintf (stderr, "Unsupported pointer encoding: %#x, "
521503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   "assuming pointer size of %d.\n", encoding, ptr_size);
521603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return ptr_size;
521725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
521825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
521925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
522025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
522125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_encoding (unsigned int val)
522225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
522325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (val & 0xf)
522425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
522525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_absptr:
522625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("absptr", stdout);
522725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
522825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_uleb128:
522925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("uleb128", stdout);
523025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
523125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata2:
523225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("udata2", stdout);
523325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
523425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata4:
523525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("udata4", stdout);
523625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
523725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata8:
523825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("udata8", stdout);
523925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
524025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sleb128:
524125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sleb128", stdout);
524225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
524325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata2:
524425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sdata2", stdout);
524525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
524625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata4:
524725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sdata4", stdout);
524825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
524925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata8:
525025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("sdata8", stdout);
525125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
525225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
525325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We did not use any of the bits after all.  */
525425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return val;
525525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
525625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
525725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return val & ~0xf;
525825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
525925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
526025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
526125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
526225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_relinfo (unsigned int val)
526325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
526425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (val & 0x70)
526525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
526625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_pcrel:
526725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("pcrel", stdout);
526825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
526925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_textrel:
527025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("textrel", stdout);
527125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
527225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_datarel:
527325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("datarel", stdout);
527425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
527525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_funcrel:
527625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("funcrel", stdout);
527725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
527825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_aligned:
527925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fputs ("aligned", stdout);
528025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
528125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
528225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return val;
528325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
528425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
528525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return val & ~0x70;
528625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
528725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
528825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
528925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
529025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_encoding_base (const char *pfx, unsigned int fde_encoding)
529125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
529225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf ("(%s", pfx);
529325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
529425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fde_encoding == DW_EH_PE_omit)
529525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    puts ("omit)");
529625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
529725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
529825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int w = fde_encoding;
529925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
530025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      w = print_encoding (w);
530125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
530225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (w & 0x70)
530325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
530425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (w != fde_encoding)
530525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    fputc_unlocked (' ', stdout);
530625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
530725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  w = print_relinfo (w);
530825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
530925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
531025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (w != 0)
531125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("%s%x", w != fde_encoding ? " " : "", w);
531225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
531325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (")");
531425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
531525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
531625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
531725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
531825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const unsigned char *
531925b3c049e70834cf33790a28643ab058b507b35cBen Chengread_encoded (unsigned int encoding, const unsigned char *readp,
532025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
532125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
532225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((encoding & 0xf) == DW_EH_PE_absptr)
532325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    encoding = gelf_getclass (dbg->elf) == ELFCLASS32
532425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
532525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
532625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (encoding & 0xf)
532725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
532825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_uleb128:
532903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      get_uleb128 (*res, readp, endp);
533025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
533125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sleb128:
533203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      get_sleb128 (*res, readp, endp);
533325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
533425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata2:
533525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 2 > endp)
533625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
533725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_2ubyte_unaligned_inc (dbg, readp);
533825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
533925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata4:
534025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 4 > endp)
534125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
534225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_4ubyte_unaligned_inc (dbg, readp);
534325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
534425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_udata8:
534525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 8 > endp)
534625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
534725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_8ubyte_unaligned_inc (dbg, readp);
534825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
534925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata2:
535025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 2 > endp)
535125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
535225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_2sbyte_unaligned_inc (dbg, readp);
535325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
535425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata4:
535525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 4 > endp)
535625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
535725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_4sbyte_unaligned_inc (dbg, readp);
535825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
535925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_EH_PE_sdata8:
536025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (readp + 8 > endp)
536125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid;
536225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *res = read_8sbyte_unaligned_inc (dbg, readp);
536325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
536425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
536525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid:
536625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (1, 0,
536725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     gettext ("invalid encoding"));
536825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
536925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
537025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return readp;
537125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
537225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
537325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
537425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
537525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
537625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
537725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
537825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
537925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We know this call will succeed since it did in the caller.  */
538025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
538125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
538225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
538303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Needed if we find PC-relative addresses.  */
538403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  GElf_Addr bias;
538503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (dwfl_module_getelf (dwflmod, &bias) == NULL)
538603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
538703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1));
538803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
538903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
539003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
539103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
539203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = (is_eh_frame
539303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    ? elf_rawdata (scn, NULL)
539403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    : dbg->sectiondata[IDX_debug_frame]);
539525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
539625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
539725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
539825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
539925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     scnname, elf_errmsg (-1));
540025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
540125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
540225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
540325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (is_eh_frame)
540425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
540525b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
540625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
540725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
540825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
540925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
541025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
541125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
541225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct cieinfo
541325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
541425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ptrdiff_t cie_offset;
541525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    const char *augmentation;
541625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    unsigned int code_alignment_factor;
541725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    unsigned int data_alignment_factor;
541825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    uint8_t address_size;
541925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    uint8_t fde_encoding;
542025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    uint8_t lsda_encoding;
542125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    struct cieinfo *next;
542225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  } *cies = NULL;
542325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
542425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
542525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = ((unsigned char *) data->d_buf
542625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					+ data->d_size);
542725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < dataend)
542825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
542925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (readp + 4 > dataend))
543025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
543125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	invalid_data:
543225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
543325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     elf_ndxscn (scn), scnname);
543425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
543525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
543625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
543725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* At the beginning there must be a CIE.  There can be multiple,
543825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 hence we test tis in a loop.  */
543925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
544025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
544125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
544225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int length = 4;
544325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (unit_length == 0xffffffff))
544425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
544525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (readp + 8 > dataend))
544625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
544725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
544825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
544925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  length = 8;
545025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
545125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
545225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (unit_length == 0))
545325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
545425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\n [%6tx] Zero terminator\n"), offset);
545525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
545625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
545725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
545803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Word maxsize = dataend - readp;
545903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (unit_length > maxsize))
546003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
546103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
546225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
546325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
546425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t start = readp - (unsigned char *) data->d_buf;
546525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *const cieend = readp + unit_length;
546625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (cieend > dataend || readp + 8 > dataend))
546725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
546825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
546925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off cie_id;
547025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (length == 4)
547125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
547225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cie_id = read_4ubyte_unaligned_inc (dbg, readp);
547325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!is_eh_frame && cie_id == DW_CIE_ID_32)
547425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    cie_id = DW_CIE_ID_64;
547525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
547625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
547725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	cie_id = read_8ubyte_unaligned_inc (dbg, readp);
547825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
547925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t version = 2;
548025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int code_alignment_factor;
548125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int data_alignment_factor;
548225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int fde_encoding = 0;
548325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int lsda_encoding = 0;
548425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word initial_location = 0;
548525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word vma_base = 0;
548625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
548725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
548825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
548925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  version = *readp++;
549025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *const augmentation = (const char *) readp;
549125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = memchr (readp, '\0', cieend - readp);
549225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (readp == NULL))
549325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
549425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++readp;
549525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
549625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint_fast8_t segment_size = 0;
549725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (version >= 4)
549825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
549925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (cieend - readp < 5)
550025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto invalid_data;
550125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ptr_size = *readp++;
550225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      segment_size = *readp++;
550325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
550425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
550503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (cieend - readp < 1)
550603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_data;
550703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (code_alignment_factor, readp, cieend);
550803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (cieend - readp < 1)
550903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_data;
551003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_sleb128 (data_alignment_factor, readp, cieend);
551125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
551225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* In some variant for unwind data there is another field.  */
551325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (strcmp (augmentation, "eh") == 0)
551425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
551525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
551625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int return_address_register;
551703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (cieend - readp < 1)
551803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_data;
551925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (version == 1))
552025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return_address_register = *readp++;
552125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
552203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    get_uleb128 (return_address_register, readp, cieend);
552325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
552425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
552525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   CIE_id:                   %" PRIu64 "\n"
552625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   version:                  %u\n"
552725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   augmentation:             \"%s\"\n",
552825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  offset, (uint64_t) unit_length, (uint64_t) cie_id,
552925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  version, augmentation);
553025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (version >= 4)
553125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("   address_size:             %u\n"
553225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    "   segment_size:             %u\n",
553325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ptr_size, segment_size);
553425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("   code_alignment_factor:    %u\n"
553525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   data_alignment_factor:    %d\n"
553625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   return_address_register:  %u\n",
553725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  code_alignment_factor,
553825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  data_alignment_factor, return_address_register);
553925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
554025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (augmentation[0] == 'z')
554125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
554225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int augmentationlen;
554303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (augmentationlen, readp, cieend);
554425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
554503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (augmentationlen > (size_t) (cieend - readp))
554603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		{
554703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  error (0, 0, gettext ("invalid augmentation length"));
554803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  readp = cieend;
554903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  continue;
555003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		}
555125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
555225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const char *hdr = "Augmentation data:";
555325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const char *cp = augmentation + 1;
555403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
555525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
555625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf ("   %-26s%#x ", hdr, *readp);
555725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  hdr = "";
555825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
555925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (*cp == 'R')
556025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
556125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      fde_encoding = *readp++;
556225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      print_encoding_base (gettext ("FDE address encoding: "),
556325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   fde_encoding);
556425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
556525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else if (*cp == 'L')
556625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
556725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      lsda_encoding = *readp++;
556825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      print_encoding_base (gettext ("LSDA pointer encoding: "),
556925b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   lsda_encoding);
557025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
557125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else if (*cp == 'P')
557225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
557325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      /* Personality.  This field usually has a relocation
557425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 attached pointing to __gcc_personality_v0.  */
557525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      const unsigned char *startp = readp;
557625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      unsigned int encoding = *readp++;
557725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      uint64_t val = 0;
557825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      readp = read_encoded (encoding, readp,
557925b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    readp - 1 + augmentationlen,
558025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &val, dbg);
558125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
558225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      while (++startp < readp)
558325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			printf ("%#x ", *startp);
558425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
558525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      putchar ('(');
558625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      print_encoding (encoding);
558725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      putchar (' ');
558825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      switch (encoding & 0xf)
558925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
559025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			case DW_EH_PE_sleb128:
559125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			case DW_EH_PE_sdata2:
559225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			case DW_EH_PE_sdata4:
559325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printf ("%" PRId64 ")\n", val);
559425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  break;
559525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			default:
559625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printf ("%#" PRIx64 ")\n", val);
559725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  break;
559825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
559925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
560025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
560125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf ("(%x)\n", *readp++);
560225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
560325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ++cp;
560425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
560525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
560625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
560725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (ptr_size == 4 || ptr_size == 8))
560825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
560925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct cieinfo *newp = alloca (sizeof (*newp));
561025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->cie_offset = offset;
561125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->augmentation = augmentation;
561225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->fde_encoding = fde_encoding;
561325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->lsda_encoding = lsda_encoding;
561425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->address_size = ptr_size;
561525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->code_alignment_factor = code_alignment_factor;
561625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->data_alignment_factor = data_alignment_factor;
561725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->next = cies;
561825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cies = newp;
561925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
562025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
562125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
562225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
562325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  struct cieinfo *cie = cies;
562425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (cie != NULL)
562525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (is_eh_frame
562625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? start - (ptrdiff_t) cie_id == cie->cie_offset
562725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: (ptrdiff_t) cie_id == cie->cie_offset)
562825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
562925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    else
563025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cie = cie->next;
563125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (cie == NULL))
563225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
563325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      puts ("invalid CIE reference in FDE");
563425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
563525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
563625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
563725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Initialize from CIE data.  */
563825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fde_encoding = cie->fde_encoding;
563925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  lsda_encoding = cie->lsda_encoding;
564025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
564125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  code_alignment_factor = cie->code_alignment_factor;
564225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data_alignment_factor = cie->data_alignment_factor;
564325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
564425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *base = readp;
564525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX There are sometimes relocations for this value
564603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
564725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Word address_range
564803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    = read_addr_unaligned_inc (ptr_size, dbg, readp);
564903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
565003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* pcrel for an FDE address is relative to the runtime
565103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     address of the start_address field itself.  Sign extend
565203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     if necessary to make sure the calculation is done on the
565303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     full 64 bit address even when initial_location only holds
565403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     the lower 32 bits.  */
565503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Addr pc_start = initial_location;
565603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (ptr_size == 4)
565703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    pc_start = (uint64_t) (int32_t) pc_start;
565803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
565903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    pc_start += ((uint64_t) shdr->sh_addr
566003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			 + (base - (const unsigned char *) data->d_buf)
566103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			 - bias);
566225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
566325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *a = format_dwarf_addr (dwflmod, cie->address_size,
566403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       pc_start, initial_location);
566525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
566625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   CIE_pointer:              %" PRIu64 "\n"
566725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "   initial_location:         %s",
566825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  offset, (uint64_t) unit_length,
566925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  cie->cie_offset, (uint64_t) cie_id, a);
567025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (a);
567125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
567225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
567325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      vma_base = (((uint64_t) shdr->sh_offset
567425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   + (base - (const unsigned char *) data->d_buf)
567525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   + (uint64_t) initial_location)
567625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  & (ptr_size == 4
567725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     ? UINT64_C (0xffffffff)
567825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     : UINT64_C (0xffffffffffffffff)));
567925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (gettext (" (offset: %#" PRIx64 ")"),
568025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (uint64_t) vma_base);
568125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
568225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
568325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n   address_range:            %#" PRIx64,
568425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (uint64_t) address_range);
568525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
568625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" (end offset: %#" PRIx64 ")"),
568725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    ((uint64_t) vma_base + (uint64_t) address_range)
568825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    & (ptr_size == 4
568925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       ? UINT64_C (0xffffffff)
569025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       : UINT64_C (0xffffffffffffffff)));
569125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar ('\n');
569225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
569325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (cie->augmentation[0] == 'z')
569425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
569525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int augmentationlen;
569603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (cieend - readp < 1)
569703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
569803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (augmentationlen, readp, cieend);
569903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
570003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (augmentationlen > (size_t) (cieend - readp))
570103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		{
570203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  error (0, 0, gettext ("invalid augmentation length"));
570303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  readp = cieend;
570403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  continue;
570503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		}
570625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
570725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (augmentationlen > 0)
570825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
570925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  const char *hdr = "Augmentation data:";
571025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  const char *cp = cie->augmentation + 1;
571125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  unsigned int u = 0;
571203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  while (*cp != '\0'
571303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			 && cp < cie->augmentation + augmentationlen + 1)
571425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
571525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (*cp == 'L')
571625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
571725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  uint64_t lsda_pointer;
571825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  const unsigned char *p
571925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    = read_encoded (lsda_encoding, &readp[u],
572025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &readp[augmentationlen],
572125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    &lsda_pointer, dbg);
572225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  u = p - readp;
572325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printf (gettext ("\
572425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   %-26sLSDA pointer: %#" PRIx64 "\n"),
572525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  hdr, lsda_pointer);
572625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  hdr = "";
572725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
572825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      ++cp;
572925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
573025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
573125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  while (u < augmentationlen)
573225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
573325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf ("   %-26s%#x\n", hdr, readp[u++]);
573425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      hdr = "";
573525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
573625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
573725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
573825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      readp += augmentationlen;
573925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
574025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
574125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
574225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Handle the initialization instructions.  */
574303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (ptr_size != 4 && ptr_size !=8)
574403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
574503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else
574603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
574703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   data_alignment_factor, version, ptr_size,
574803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   dwflmod, ebl, dbg);
574925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = cieend;
575025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
575125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
575225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
575325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
575425b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct attrcb_args
575525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
575625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwfl_Module *dwflmod;
575725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf *dbg;
575803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Die *die;
575925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int level;
576025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool silent;
576125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int version;
576225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int addrsize;
576325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int offset_size;
576403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct Dwarf_CU *cu;
576525b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
576625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
576725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
576825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
576925b3c049e70834cf33790a28643ab058b507b35cBen Chengattr_callback (Dwarf_Attribute *attrp, void *arg)
577025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
577125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct attrcb_args *cbargs = (struct attrcb_args *) arg;
577225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const int level = cbargs->level;
577325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
577425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int attr = dwarf_whatattr (attrp);
577525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (attr == 0))
577625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
577725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!cbargs->silent)
577825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get attribute code: %s"),
577925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       dwarf_errmsg (-1));
578025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return DWARF_CB_ABORT;
578125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
578225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
578325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int form = dwarf_whatform (attrp);
578425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (form == 0))
578525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
578625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!cbargs->silent)
578725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get attribute form: %s"),
578825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       dwarf_errmsg (-1));
578925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return DWARF_CB_ABORT;
579025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
579125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
579225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (form)
579325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
579425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_addr:
579525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!cbargs->silent)
579625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
579725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Addr addr;
579825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
579925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
580025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    attrval_out:
580125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!cbargs->silent)
580225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		error (0, 0, gettext ("cannot get attribute value: %s"),
580325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       dwarf_errmsg (-1));
580425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return DWARF_CB_ABORT;
580525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
580603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
580703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       addr, addr);
580825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("           %*s%-20s (%s) %s\n",
580903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (int) (level * 2), "", dwarf_attr_name (attr),
581003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  dwarf_form_name (form), a);
581125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (a);
581225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
581325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
581425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
581525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_indirect:
581625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_strp:
581725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_string:
581803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case DW_FORM_GNU_strp_alt:
581925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
582025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
582125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *str = dwarf_formstring (attrp);
582225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (str == NULL))
582325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
582425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) \"%s\"\n",
582503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (int) (level * 2), "", dwarf_attr_name (attr),
582603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      dwarf_form_name (form), str);
582725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
582825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
582925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref_addr:
583025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref_udata:
583125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref8:
583225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref4:
583325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref2:
583403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case DW_FORM_ref1:
583503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case DW_FORM_GNU_ref_alt:
583625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
583725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
583825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die ref;
583925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
584025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
584125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
584225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) [%6" PRIxMAX "]\n",
584303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (int) (level * 2), "", dwarf_attr_name (attr),
584403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref));
584525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
584625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
584725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_ref_sig8:
584825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
584925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
585025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
585103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (int) (level * 2), "", dwarf_attr_name (attr),
585203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      dwarf_form_name (form),
585303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
585425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
585525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
585625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_sec_offset:
585725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_udata:
585825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_sdata:
585925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data8:
586025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data4:
586125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data2:
586225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_data1:;
586325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word num;
586425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formudata (attrp, &num) != 0))
586525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
586625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
586725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *valuestr = NULL;
586825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (attr)
586925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
587025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This case can take either a constant or a loclistptr.  */
587125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_member_location:
587225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (form != DW_FORM_sec_offset
587325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (cbargs->version >= 4
587425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (form != DW_FORM_data4 && form != DW_FORM_data8)))
587525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
587625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!cbargs->silent)
587725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("           %*s%-20s (%s) %" PRIxMAX "\n",
587803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			(int) (level * 2), "", dwarf_attr_name (attr),
587903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			dwarf_form_name (form), (uintmax_t) num);
588025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return DWARF_CB_OK;
588125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
588225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* else fallthrough */
588325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
588425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* These cases always take a loclistptr and no constant. */
588525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_location:
588625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_location:
588725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_vtable_elem_location:
588825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_string_length:
588925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_use_location:
589025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_frame_base:
589125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_return_addr:
589225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_static_link:
589325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_value:
589425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_data_value:
589525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target:
589625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target_clobbered:
589703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  {
589803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    bool nlpt = notice_listptr (section_loc, &known_loclistptr,
589903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					cbargs->addrsize, cbargs->offset_size,
590003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					cbargs->cu, num);
590103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if (!cbargs->silent)
590203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
590303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      (int) (level * 2), "", dwarf_attr_name (attr),
590403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      dwarf_form_name (form), (uintmax_t) num,
590503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      nlpt ? "" : " <WARNING offset too big>");
590603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  }
590725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return DWARF_CB_OK;
590825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
590925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_ranges:
591003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  {
591103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    bool nlpt = notice_listptr (section_ranges, &known_rangelistptr,
591203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					cbargs->addrsize, cbargs->offset_size,
591303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					cbargs->cu, num);
591403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if (!cbargs->silent)
591503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("           %*s%-20s (%s) range list [%6" PRIxMAX "]%s\n",
591603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      (int) (level * 2), "", dwarf_attr_name (attr),
591703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      dwarf_form_name (form), (uintmax_t) num,
591803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      nlpt ? "" : " <WARNING offset too big>");
591903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  }
592025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return DWARF_CB_OK;
592125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
592225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_language:
592303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_lang_name (num);
592425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
592525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_encoding:
592603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_encoding_name (num);
592725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
592825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_accessibility:
592903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_access_name (num);
593025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
593125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_visibility:
593203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_visibility_name (num);
593325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
593425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_virtuality:
593503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_virtuality_name (num);
593625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
593725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_identifier_case:
593803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_identifier_case_name (num);
593925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
594025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_calling_convention:
594103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_calling_convention_name (num);
594225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
594325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_inline:
594403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_inline_name (num);
594525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
594625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_ordering:
594703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_ordering_name (num);
594825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
594925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_discr_list:
595003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  valuestr = dwarf_discr_list_name (num);
595125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
595225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
595325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Nothing.  */
595425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
595525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
595625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
595725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
595825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
595925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
596003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* When highpc is in constant form it is relative to lowpc.
596103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 In that case also show the address.  */
596203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Addr highpc;
596303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0)
596403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
596503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
596603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       highpc, highpc);
596703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf ("           %*s%-20s (%s) %" PRIuMAX " (%s)\n",
596803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (int) (level * 2), "", dwarf_attr_name (attr),
596903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  dwarf_form_name (form), (uintmax_t) num, a);
597003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  free (a);
597103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
597225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
597303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
597403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Sword snum = 0;
597503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (form == DW_FORM_sdata)
597603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
597703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      goto attrval_out;
597803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
597903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (valuestr == NULL)
598003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
598103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("           %*s%-20s (%s)",
598203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      (int) (level * 2), "", dwarf_attr_name (attr),
598303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      dwarf_form_name (form));
598403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (form == DW_FORM_sdata)
598503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf (" %" PRIdMAX "\n", (intmax_t) snum);
598603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else
598703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf (" %" PRIuMAX "\n", (uintmax_t) num);
598803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
598903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else
599003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
599103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("           %*s%-20s (%s) %s",
599203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      (int) (level * 2), "", dwarf_attr_name (attr),
599303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      dwarf_form_name (form), valuestr);
599403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (form == DW_FORM_sdata)
599503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf (" (%" PRIdMAX ")\n", (intmax_t) snum);
599603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else
599703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf (" (%" PRIuMAX ")\n", (uintmax_t) num);
599803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
599903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
600025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
600125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
600225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_flag:
600325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
600425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
600525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool flag;
600625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formflag (attrp, &flag) != 0))
600725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
600825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
600925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) %s\n",
601003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (int) (level * 2), "", dwarf_attr_name (attr),
601103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR));
601225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
601325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
601425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_flag_present:
601525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
601625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
601725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) %s\n",
601803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (int) (level * 2), "", dwarf_attr_name (attr),
601903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      dwarf_form_name (form), nl_langinfo (YESSTR));
602025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
602125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
602225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_exprloc:
602325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block4:
602425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block2:
602525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block1:
602625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case DW_FORM_block:
602725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
602825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
602925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Block block;
603025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (dwarf_formblock (attrp, &block) != 0))
603125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto attrval_out;
603225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
603325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (%s) ",
603403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (int) (level * 2), "", dwarf_attr_name (attr),
603503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      dwarf_form_name (form));
603625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
603725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (attr)
603825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
603925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
604025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (form != DW_FORM_exprloc)
604125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
604225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      print_block (block.length, block.data);
604325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
604425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
604525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Fall through.  */
604625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
604725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_location:
604825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_location:
604925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_data_member_location:
605025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_vtable_elem_location:
605125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_string_length:
605225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_use_location:
605325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_frame_base:
605425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_return_addr:
605525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_static_link:
605625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_allocated:
605725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_associated:
605825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_bit_size:
605925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_bit_offset:
606025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_bit_stride:
606125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_byte_size:
606225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_byte_stride:
606325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_count:
606425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_lower_bound:
606525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_upper_bound:
606625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_value:
606725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_data_value:
606825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target:
606925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_AT_GNU_call_site_target_clobbered:
607025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  putchar ('\n');
607125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_ops (cbargs->dwflmod, cbargs->dbg,
607225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     12 + level * 2, 12 + level * 2,
607325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     cbargs->version, cbargs->addrsize, cbargs->offset_size,
607403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		     attrp->cu, block.length, block.data);
607525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
607625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
607725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
607825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
607925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
608025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (cbargs->silent)
608125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
608225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("           %*s%-20s (form: %#x) ???\n",
608303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (int) (level * 2), "", dwarf_attr_name (attr),
608425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) form);
608525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
608625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
608725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
608825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return DWARF_CB_OK;
608925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
609025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
609125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
609225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_units (Dwfl_Module *dwflmod,
609325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Ebl *ebl, GElf_Ehdr *ehdr,
609425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Elf_Scn *scn, GElf_Shdr *shdr,
609525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   Dwarf *dbg, bool debug_types)
609625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
609725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const bool silent = !(print_debug_sections & section_info);
609825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *secname = section_name (ebl, ehdr, shdr);
609925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
610025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!silent)
610125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\
610225b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
610325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
610425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
610525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If the section is empty we don't have to do anything.  */
610625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!silent && shdr->sh_size == 0)
610725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
610825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
610925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int maxdies = 20;
611025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
611125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
611225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset = 0;
611325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
611425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* New compilation unit.  */
611525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t cuhl;
611625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Half version;
611725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off abbroffset;
611825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint8_t addrsize;
611925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint8_t offsize;
612025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off nextcu;
612125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint64_t typesig;
612225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off typeoff;
612325b3c049e70834cf33790a28643ab058b507b35cBen Cheng next_cu:
612425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
612525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       &abbroffset, &addrsize, &offsize,
612625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       debug_types ? &typesig : NULL,
612725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       debug_types ? &typeoff : NULL) != 0)
612825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto do_return;
612925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
613025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!silent)
613125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
613225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (debug_types)
613325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" Type unit at offset %" PRIu64 ":\n"
613425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 " Version: %" PRIu16 ", Abbreviation section offset: %"
613525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 PRIu64 ", Address size: %" PRIu8
613625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", Offset size: %" PRIu8
613725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 "\n Type signature: %#" PRIx64
613825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", Type offset: %#" PRIx64 "\n"),
613925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) offset, version, abbroffset, addrsize, offsize,
614025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		typesig, (uint64_t) typeoff);
614125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
614225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
614325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 " Version: %" PRIu16 ", Abbreviation section offset: %"
614425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 PRIu64 ", Address size: %" PRIu8
614525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ", Offset size: %" PRIu8 "\n"),
614625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) offset, version, abbroffset, addrsize, offsize);
614725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
614825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
614925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct attrcb_args args =
615025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
615125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .dwflmod = dwflmod,
615225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .dbg = dbg,
615325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .silent = silent,
615425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .version = version,
615525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .addrsize = addrsize,
615603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      .offset_size = offsize
615725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
615825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
615925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  offset += cuhl;
616025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
616125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int level = 0;
616225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
616325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
616425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(dbg, offset, &dies[level]) == NULL))
616525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
616625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!silent)
616725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
616825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      " in section '%s': %s"),
616925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       (uint64_t) offset, secname, dwarf_errmsg (-1));
617025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto do_return;
617125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
617225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
617303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  args.cu = dies[0].cu;
617403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
617525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
617625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
617725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset = dwarf_dieoffset (&dies[level]);
617825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (offset == ~0ul))
617925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
618025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!silent)
618125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("cannot get DIE offset: %s"),
618225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   dwarf_errmsg (-1));
618325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto do_return;
618425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
618525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
618625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int tag = dwarf_tag (&dies[level]);
618725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (tag == DW_TAG_invalid))
618825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
618925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!silent)
619025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
619125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  " in section '%s': %s"),
619225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   (uint64_t) offset, secname, dwarf_errmsg (-1));
619325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto do_return;
619425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
619525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
619625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!silent)
619725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (" [%6" PRIx64 "]  %*s%s\n",
619825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) offset, (int) (level * 2), "",
619903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		dwarf_tag_name (tag));
620025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
620125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Print the attribute values.  */
620225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      args.level = level;
620303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      args.die = &dies[level];
620425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
620525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
620625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Make room for the next level's DIE.  */
620725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (level + 1 == maxdies)
620825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	dies = (Dwarf_Die *) xrealloc (dies,
620925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       (maxdies += 10)
621025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       * sizeof (Dwarf_Die));
621125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
621225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int res = dwarf_child (&dies[level], &dies[level + 1]);
621325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (res > 0)
621425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
621525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
621625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (level-- == 0)
621725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
621825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
621925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (res == -1))
622025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
622125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!silent)
622225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		error (0, 0, gettext ("cannot get next DIE: %s\n"),
622325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       dwarf_errmsg (-1));
622425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      goto do_return;
622525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
622625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
622725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (unlikely (res < 0))
622825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
622925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!silent)
623025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("cannot get next DIE: %s"),
623125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   dwarf_errmsg (-1));
623225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto do_return;
623325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
623425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
623525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	++level;
623625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
623725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (level >= 0);
623825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
623925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  offset = nextcu;
624025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (offset != 0)
624125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     goto next_cu;
624225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
624325b3c049e70834cf33790a28643ab058b507b35cBen Cheng do_return:
624425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (dies);
624525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
624625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
624725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
624825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
624925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
625025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
625125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
625225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
625325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
625525b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
625625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
625725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
625825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
625925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
626025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
626125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
626225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
626303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
626403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
626503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
626603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  printf (gettext ("\
626703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
626803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
626903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  (uint64_t) shdr->sh_offset);
627003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
627103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t address_size
627203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
627303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
627403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Off cuoffset;
627503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Off ncuoffset = 0;
627603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t hsize;
627703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
627803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		       NULL, NULL, NULL) == 0)
627903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
628003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Die cudie;
628103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
628203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
628303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
628403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      size_t nlines;
628503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Lines *lines;
628603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwarf_getsrclines (&cudie, &lines, &nlines) != 0)
628703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
628803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
628903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (" CU [%" PRIx64 "] %s\n",
629003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
629103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf ("  line:col SBPE* disc isa op address"
629203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      " (Statement Block Prologue Epilogue *End)\n");
629303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const char *last_file = "";
629403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      for (size_t n = 0; n < nlines; n++)
629503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
629603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Line *line = dwarf_onesrcline (lines, n);
629703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (line == NULL)
629803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
629903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("  dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
630003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      continue;
630103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
630203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Word mtime, length;
630303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  const char *file = dwarf_linesrc (line, &mtime, &length);
630403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (file == NULL)
630503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
630603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("  <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
630703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      last_file = "";
630803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
630903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else if (strcmp (last_file, file) != 0)
631003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
631103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("  %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
631203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      file, mtime, length);
631303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      last_file = file;
631403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
631503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
631603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  int lineno, colno;
631703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  bool statement, endseq, block, prologue_end, epilogue_begin;
631803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  unsigned int lineop, isa, disc;
631903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  Dwarf_Addr address;
632003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineaddr (line, &address);
632103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineno (line, &lineno);
632203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_linecol (line, &colno);
632303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineop_index (line, &lineop);
632403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_linebeginstatement (line, &statement);
632503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineendsequence (line, &endseq);
632603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineblock (line, &block);
632703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineprologueend (line, &prologue_end);
632803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineepiloguebegin (line, &epilogue_begin);
632903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_lineisa (line, &isa);
633003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwarf_linediscriminator (line, &disc);
633103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
633203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* End sequence is special, it is one byte past.  */
633303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *a = format_dwarf_addr (dwflmod, address_size,
633403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       address - (endseq ? 1 : 0), address);
633503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf ("  %4d:%-3d %c%c%c%c%c %4d %3d %2d %s\n",
633603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  lineno, colno,
633703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (statement ? 'S' : ' '),
633803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (block ? 'B' : ' '),
633903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (prologue_end ? 'P' : ' '),
634003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (epilogue_begin ? 'E' : ' '),
634103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (endseq ? '*' : ' '),
634203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  disc, isa, lineop, a);
634303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  free (a);
634403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
634503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (endseq)
634603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    printf("\n");
634703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
634803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
634903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
635003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
635103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
635203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
635325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
635425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
635525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
635603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (decodedline)
635703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
635803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
635903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
636003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
636103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
636225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
636325b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
636425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
636525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
636625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
636725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_size == 0)
636825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
636925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
637025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* There is no functionality in libdw to read the information in the
637125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     way it is represented here.  Hardcode the decoder.  */
637203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = dbg->sectiondata[IDX_debug_line];
637325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL || data->d_buf == NULL))
637425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
637525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get line data section data: %s"),
637625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
637725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
637825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
637925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
638025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *linep = (const unsigned char *) data->d_buf;
638125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *lineendp;
638225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
638325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (linep
638425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
638525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
638625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t start_offset = linep - (const unsigned char *) data->d_buf;
638725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
638825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
638925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
639003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (linep + 4 > lineendp))
639103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
639225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
639325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int length = 4;
639425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (unit_length == 0xffffffff))
639525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
639625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (linep + 8 > lineendp))
639725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
639825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    invalid_data:
639925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
640025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
640125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
640225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
640325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
640425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  length = 8;
640525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
640625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
640725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Check whether we have enough room in the section.  */
640803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (unit_length > (size_t) (lineendp - linep)
640903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  || unit_length < 2 + length + 5 * 1))
641025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
641125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      lineendp = linep + unit_length;
641225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
641325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The next element of the header is the version identifier.  */
641425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
641525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
641625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Next comes the header length.  */
641725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word header_length;
641825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (length == 4)
641925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	header_length = read_4ubyte_unaligned_inc (dbg, linep);
642025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
642125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	header_length = read_8ubyte_unaligned_inc (dbg, linep);
642225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      //const unsigned char *header_start = linep;
642325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
642425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Next the minimum instruction length.  */
642525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t minimum_instr_len = *linep++;
642625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
642725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Next the maximum operations per instruction, in version 4 format.  */
642825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
642925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
643025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Then the flag determining the default value of the is_stmt
643125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   register.  */
643225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t default_is_stmt = *linep++;
643325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
643425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Now the line base.  */
643525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int_fast8_t line_base = *((const int_fast8_t *) linep);
643625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++linep;
643725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
643825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* And the line range.  */
643925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t line_range = *linep++;
644025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
644125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The opcode base.  */
644225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t opcode_base = *linep++;
644325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
644425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Print what we got so far.  */
644525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\n"
644625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Length:                     %" PRIu64 "\n"
644725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " DWARF version:              %" PRIuFAST16 "\n"
644825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Prologue length:            %" PRIu64 "\n"
644925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Minimum instruction length: %" PRIuFAST8 "\n"
645025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Maximum operations per instruction: %" PRIuFAST8 "\n"
645125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Initial value if '%s': %" PRIuFAST8 "\n"
645225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Line base:                  %" PRIdFAST8 "\n"
645325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Line range:                 %" PRIuFAST8 "\n"
645425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       " Opcode base:                %" PRIuFAST8 "\n"
645525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "\n"
645625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "Opcodes:\n"),
645725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (uint64_t) unit_length, version, (uint64_t) header_length,
645825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      minimum_instr_len, max_ops_per_instr,
645925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      "is_stmt", default_is_stmt, line_base,
646025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      line_range, opcode_base);
646125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
646225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (linep + opcode_base - 1 >= lineendp))
646325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
646425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	invalid_unit:
646525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0,
646625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
646725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 linep - (const unsigned char *) data->d_buf,
646825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
646925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  linep = lineendp;
647025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  continue;
647125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
647225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int opcode_base_l10 = 1;
647325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int tmp = opcode_base;
647425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (tmp > 10)
647525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
647625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  tmp /= 10;
647725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++opcode_base_l10;
647825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
647925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const uint8_t *standard_opcode_lengths = linep - 1;
648025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
648125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
648225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
648325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (int) linep[cnt - 1]),
648425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		opcode_base_l10, cnt, linep[cnt - 1]);
648525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      linep += opcode_base - 1;
648625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (linep >= lineendp))
648725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_unit;
648825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
648925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext ("\nDirectory table:"));
649025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (*linep != 0)
649125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
649225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
649325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (endp == NULL))
649425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_unit;
649525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
649625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" %s\n", (char *) linep);
649725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
649825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  linep = endp + 1;
649925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
650025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Skip the final NUL byte.  */
650125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++linep;
650225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
650325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (linep >= lineendp))
650425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_unit;
650525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext ("\nFile name table:\n"
650625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     " Entry Dir   Time      Size      Name"));
650725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (unsigned int cnt = 1; *linep != 0; ++cnt)
650825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
650925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* First comes the file name.  */
651025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *fname = (char *) linep;
651125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
651225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (endp == NULL))
651325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_unit;
651425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  linep = endp + 1;
651525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
651625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Then the index.  */
651725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int diridx;
651803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (lineendp - linep < 1)
651903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_unit;
652003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (diridx, linep, lineendp);
652125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
652225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Next comes the modification time.  */
652325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int mtime;
652403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (lineendp - linep < 1)
652503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_unit;
652603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (mtime, linep, lineendp);
652725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
652825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Finally the length of the file.  */
652925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int fsize;
653003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (lineendp - linep < 1)
653103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_unit;
653203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (fsize, linep, lineendp);
653325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
653425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" %-5u %-5u %-9u %-9u %s\n",
653525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  cnt, diridx, mtime, fsize, fname);
653625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
653725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Skip the final NUL byte.  */
653825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++linep;
653925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
654025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts (gettext ("\nLine number statements:"));
654125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word address = 0;
654225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int op_index = 0;
654325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t line = 1;
654425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t is_stmt = default_is_stmt;
654525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
654625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Default address value, in case we do not find the CU.  */
654725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t address_size
654825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
654925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
655025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Determine the CU this block is for.  */
655125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off cuoffset;
655225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Off ncuoffset = 0;
655325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t hsize;
655425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
655525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   NULL, NULL, NULL) == 0)
655625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
655725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Die cudie;
655825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
655925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
656025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Attribute stmt_list;
656125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
656225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
656325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Dwarf_Word lineoff;
656425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
656525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
656625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (lineoff == start_offset)
656725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
656825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Found the CU.  */
656925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      address_size = cudie.cu->address_size;
657025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
657125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
657225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
657325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
657425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Apply the "operation advance" from a special opcode
657525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
657625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int op_addr_advance;
657725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool show_op_index;
657825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      inline void advance_pc (unsigned int op_advance)
657925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
658025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	op_addr_advance = minimum_instr_len * ((op_index + op_advance)
658125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       / max_ops_per_instr);
658225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	address += op_advance;
658325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	show_op_index = (op_index > 0 ||
658425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (op_index + op_advance) % max_ops_per_instr > 0);
658525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	op_index = (op_index + op_advance) % max_ops_per_instr;
658625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
658725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
658803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (max_ops_per_instr == 0)
658903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
659003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0,
659103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 gettext ("invalid maximum operations per instruction is zero"));
659203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  linep = lineendp;
659303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  continue;
659403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
659503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
659625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (linep < lineendp)
659725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
659825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t offset = linep - (const unsigned char *) data->d_buf;
659925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int u128;
660025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int s128;
660125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
660225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Read the opcode.  */
660325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned int opcode = *linep++;
660425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
660525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%6" PRIx64 "]", (uint64_t)offset);
660625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Is this a special opcode?  */
660725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (opcode >= opcode_base))
660825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
660903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (unlikely (line_range == 0))
661003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_unit;
661103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
661225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Yes.  Handling this is quite easy since the opcode value
661325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 is computed with
661425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
661525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 opcode = (desired line increment - line_base)
661625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   + (line_range * address advance) + opcode_base
661725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      */
661825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int line_increment = (line_base
661925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    + (opcode - opcode_base) % line_range);
662025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
662125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Perform the increments.  */
662225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      line += line_increment;
662325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      advance_pc ((opcode - opcode_base) / line_range);
662425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
662503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      char *a = format_dwarf_addr (dwflmod, 0, address, address);
662625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (show_op_index)
662725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf (gettext ("\
662825b3c049e70834cf33790a28643ab058b507b35cBen Cheng special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
662925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			opcode, op_addr_advance, a, op_index,
663025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			line_increment, line);
663125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
663225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf (gettext ("\
663325b3c049e70834cf33790a28643ab058b507b35cBen Cheng special opcode %u: address+%u = %s, line%+d = %zu\n"),
663425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			opcode, op_addr_advance, a, line_increment, line);
663525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      free (a);
663625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
663725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (opcode == 0)
663825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
663925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This an extended opcode.  */
664025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (linep + 2 > lineendp))
664125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto invalid_unit;
664225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
664325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The length.  */
664425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unsigned int len = *linep++;
664525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
664625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (linep + len > lineendp))
664725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto invalid_unit;
664825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
664925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The sub-opcode.  */
665025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      opcode = *linep++;
665125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
665225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (gettext (" extended opcode %u: "), opcode);
665325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
665425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      switch (opcode)
665525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
665625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_end_sequence:
665725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" end of sequence"));
665825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
665925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Reset the registers we care about.  */
666025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  address = 0;
666125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  op_index = 0;
666225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  line = 1;
666325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_stmt = default_is_stmt;
666425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
666525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
666625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_set_address:
666725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  op_index = 0;
666803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  if (unlikely ((size_t) (lineendp - linep) < address_size))
666903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    goto invalid_unit;
667025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (address_size == 4)
667125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    address = read_4ubyte_unaligned_inc (dbg, linep);
667225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
667325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    address = read_8ubyte_unaligned_inc (dbg, linep);
667425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
667503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    char *a = format_dwarf_addr (dwflmod, 0, address, address);
667625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext (" set address to %s\n"), a);
667725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
667825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
667925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
668025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
668125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_define_file:
668225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
668325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    char *fname = (char *) linep;
668425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    unsigned char *endp = memchr (linep, '\0',
668525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						  lineendp - linep);
668625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (unlikely (endp == NULL))
668725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      goto invalid_unit;
668825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    linep = endp + 1;
668925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
669025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    unsigned int diridx;
669103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    if (lineendp - linep < 1)
669203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      goto invalid_unit;
669303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    get_uleb128 (diridx, linep, lineendp);
669425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    Dwarf_Word mtime;
669503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    if (lineendp - linep < 1)
669603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      goto invalid_unit;
669703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    get_uleb128 (mtime, linep, lineendp);
669825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    Dwarf_Word filelength;
669903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    if (lineendp - linep < 1)
670003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      goto invalid_unit;
670103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    get_uleb128 (filelength, linep, lineendp);
670225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
670325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("\
670425b3c049e70834cf33790a28643ab058b507b35cBen Cheng define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
670525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    diridx, (uint64_t) mtime, (uint64_t) filelength,
670625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    fname);
670725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
670825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
670925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
671025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNE_set_discriminator:
671125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one ULEB128 parameter, the discriminator.  */
671225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
671325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
671425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
671503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  get_uleb128 (u128, linep, lineendp);
671625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set discriminator to %u\n"), u128);
671725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
671825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
671925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		default:
672025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Unknown, ignore it.  */
672125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" unknown opcode"));
672225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  linep += len - 1;
672325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
672425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
672525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
672625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (opcode <= DW_LNS_set_isa)
672725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
672825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is a known standard opcode.  */
672925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      switch (opcode)
673025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
673125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_copy:
673225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
673325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" copy"));
673425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
673525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
673625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_advance_pc:
673725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is added to the
673825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     address.  */
673903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  get_uleb128 (u128, linep, lineendp);
674025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  advance_pc (u128);
674125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
674203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    char *a = format_dwarf_addr (dwflmod, 0, address, address);
674325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (show_op_index)
674425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext ("\
674525b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by %u to %s, op_index to %u\n"),
674625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a, op_index);
674725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else
674825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext (" advance address by %u to %s\n"),
674925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a);
675025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
675125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
675225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
675325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
675425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_advance_line:
675525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one sleb128 parameter which is added to the
675625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     line.  */
675703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  get_sleb128 (s128, linep, lineendp);
675825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  line += s128;
675925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext ("\
676025b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance line by constant %d to %" PRId64 "\n"),
676125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  s128, (int64_t) line);
676225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
676325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
676425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_file:
676525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is stored in file.  */
676603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  get_uleb128 (u128, linep, lineendp);
676725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set file to %" PRIu64 "\n"),
676825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (uint64_t) u128);
676925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
677025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
677125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_column:
677225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is stored in column.  */
677325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
677425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
677525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
677603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  get_uleb128 (u128, linep, lineendp);
677725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set column to %" PRIu64 "\n"),
677825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (uint64_t) u128);
677925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
678025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
678125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_negate_stmt:
678225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
678325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  is_stmt = 1 - is_stmt;
678425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
678525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  "is_stmt", is_stmt);
678625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
678725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
678825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_basic_block:
678925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
679025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" set basic block flag"));
679125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
679225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
679325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_const_add_pc:
679425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
679503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
679603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  if (unlikely (line_range == 0))
679703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    goto invalid_unit;
679803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
679925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  advance_pc ((255 - opcode_base) / line_range);
680025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
680103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    char *a = format_dwarf_addr (dwflmod, 0, address, address);
680225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (show_op_index)
680325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext ("\
680425b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by constant %u to %s, op_index to %u\n"),
680525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a, op_index);
680625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else
680725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      printf (gettext ("\
680825b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by constant %u to %s\n"),
680925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      op_addr_advance, a);
681025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
681125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
681225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
681325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
681425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_fixed_advance_pc:
681525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one 16 bit parameter which is added to the
681625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     address.  */
681725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
681825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
681925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
682025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
682125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  address += u128;
682225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  op_index = 0;
682325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
682403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    char *a = format_dwarf_addr (dwflmod, 0, address, address);
682525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf (gettext ("\
682625b3c049e70834cf33790a28643ab058b507b35cBen Cheng advance address by fixed value %u to %s\n"),
682725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    u128, a);
682825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    free (a);
682925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
683025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
683125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
683225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_prologue_end:
683325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
683425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" set prologue end flag"));
683525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
683625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
683725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_epilogue_begin:
683825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes no argument.  */
683925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  puts (gettext (" set epilogue begin flag"));
684025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
684125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
684225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		case DW_LNS_set_isa:
684325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Takes one uleb128 parameter which is stored in isa.  */
684425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (standard_opcode_lengths[opcode] != 1))
684525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    goto invalid_unit;
684625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
684703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  get_uleb128 (u128, linep, lineendp);
684825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (gettext (" set isa to %u\n"), u128);
684925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
685025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
685125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
685225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
685325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
685425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is a new opcode the generator but not we know about.
685525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 Read the parameters associated with it but then discard
685625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 everything.  Read all the parameters for this opcode.  */
685725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
685825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				" unknown opcode with %" PRIu8 " parameters:",
685925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				standard_opcode_lengths[opcode]),
686025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      standard_opcode_lengths[opcode]);
686125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
686225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
686303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  get_uleb128 (u128, linep, lineendp);
686425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (n != standard_opcode_lengths[opcode])
686525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    putc_unlocked (',', stdout);
686625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf (" %u", u128);
686725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
686825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
686925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Next round, ignore this opcode.  */
687025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
687125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
687225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
687325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
687425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
687525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* There must only be one data block.  */
687625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (elf_getdata (scn, data) == NULL);
687725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
687825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
687925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
688025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
688125b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_loc_section (Dwfl_Module *dwflmod,
688225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Ebl *ebl, GElf_Ehdr *ehdr,
688325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
688425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
688503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = dbg->sectiondata[IDX_debug_loc];
688625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
688725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
688825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
688925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get .debug_loc content: %s"),
689025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
689125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
689225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
689325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
689425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
689525b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
689625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
689725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
689825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
689925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sort_listptr (&known_loclistptr, "loclistptr");
690025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t listptr_idx = 0;
690125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
690225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
690325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t offset_size = 4;
690425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
690525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool first = true;
690603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct Dwarf_CU *cu = NULL;
690703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Addr base = 0;
690825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *readp = data->d_buf;
690925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
691025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < endp)
691125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
691225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
691325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
691425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
691503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				      &address_size, &offset_size, &base,
691603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				      &cu, offset, &readp, endp))
691725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
691825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
691903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (data->d_size - offset < (size_t) address_size * 2))
692025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
692125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
692225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
692325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
692425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
692525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr begin;
692625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Addr end;
692725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (address_size == 8)
692825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
692925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_8ubyte_unaligned_inc (dbg, readp);
693025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_8ubyte_unaligned_inc (dbg, readp);
693125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
693225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
693325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
693425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  begin = read_4ubyte_unaligned_inc (dbg, readp);
693525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  end = read_4ubyte_unaligned_inc (dbg, readp);
693625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (begin == (Dwarf_Addr) (uint32_t) -1)
693725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    begin = (Dwarf_Addr) -1l;
693825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
693925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
694025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
694125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
694203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *b = format_dwarf_addr (dwflmod, address_size, end, end);
694325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
694425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
694503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  base = end;
694625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
694725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (begin == 0 && end == 0) /* End of list entry.  */
694825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
694925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)
695025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  empty list\n"), offset);
695125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = true;
695225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
695325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
695425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
695525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We have a location expression entry.  */
695625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
695725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
695803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
695903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       begin);
696003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *e = format_dwarf_addr (dwflmod, address_size, base + end,
696103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       end);
696225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
696325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (first)		/* First entry in a list.  */
696425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
696525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
696625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (gettext ("           %s..%s"), b, e);
696725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
696825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (b);
696925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  free (e);
697025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
697125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (endp - readp <= (ptrdiff_t) len)
697225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
697325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      fputs (gettext ("   <INVALID DATA>\n"), stdout);
697425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
697525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
697625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
697725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
697803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		     3 /*XXX*/, address_size, offset_size, cu, len, readp);
697925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
698025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  first = false;
698125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp += len;
698225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
698325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
698425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
698525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
698625b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct mac_culist
698725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
698825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Die die;
698925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset;
699025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Files *files;
699125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *next;
699225b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
699325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
699425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
699525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
699625b3c049e70834cf33790a28643ab058b507b35cBen Chengmac_compare (const void *p1, const void *p2)
699725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
699825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *m1 = (struct mac_culist *) p1;
699925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *m2 = (struct mac_culist *) p2;
700025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
700125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (m1->offset < m2->offset)
700225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
700325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (m1->offset > m2->offset)
700425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 1;
700525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
700625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
700725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
700825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
700925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
701025b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
701125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Ebl *ebl, GElf_Ehdr *ehdr,
701225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
701325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
701425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
701525b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
701625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
701725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
701825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  putc_unlocked ('\n', stdout);
701925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
702025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* There is no function in libdw to iterate over the raw content of
702125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     the section but it is easy enough to do.  */
702203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = dbg->sectiondata[IDX_debug_macinfo];
702325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL || data->d_buf == NULL))
702425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
702525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get macro information section data: %s"),
702625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf_errmsg (-1));
702725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
702825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
702925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
703025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the source file information for all CUs.  */
703125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset;
703225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off ncu = 0;
703325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t hsize;
703425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *culist = NULL;
703525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nculist = 0;
703625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
703725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
703825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Die cudie;
703925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
704025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
704125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
704225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Attribute attr;
704325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
704425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
704525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
704625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word macoff;
704725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (dwarf_formudata (&attr, &macoff) != 0)
704825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
704925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
705025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
705125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->die = cudie;
705225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->offset = macoff;
705325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->files = NULL;
705425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->next = culist;
705525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      culist = newp;
705625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++nculist;
705725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
705825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
705925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Convert the list into an array for easier consumption.  */
706025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
706125b3c049e70834cf33790a28643ab058b507b35cBen Cheng							 * sizeof (*cus));
706225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Add sentinel.  */
706325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  cus[nculist].offset = data->d_size;
706425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nculist > 0)
706525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
706625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t cnt = nculist - 1; culist != NULL; --cnt)
706725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
706825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (cnt < nculist);
706925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cus[cnt] = *culist;
707025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  culist = culist->next;
707125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
707225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
707325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Sort the array according to the offset in the .debug_macinfo
707425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 section.  Note we keep the sentinel at the end.  */
707525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      qsort (cus, nculist, sizeof (*cus), mac_compare);
707625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
707725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
707825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = (const unsigned char *) data->d_buf;
707925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readendp = readp + data->d_size;
708025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int level = 1;
708125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
708225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < readendp)
708325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
708425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int opcode = *readp++;
708525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int u128;
708625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int u128_2;
708725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *endp;
708825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
708925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (opcode)
709025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
709125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_define:
709225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_undef:
709325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_vendor_ext:
709425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /*  For the first two opcodes the parameters are
709525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		line, string
709625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      For the latter
709725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		number, string.
709825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      We can treat these cases together.  */
709903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (u128, readp, readendp);
710025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
710125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  endp = memchr (readp, '\0', readendp - readp);
710225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (endp == NULL))
710325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
710425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf (gettext ("\
710525b3c049e70834cf33790a28643ab058b507b35cBen Cheng%*s*** non-terminated string at end of section"),
710625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      level, "");
710725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return;
710825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
710925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
711025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (opcode == DW_MACINFO_define)
711125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s#define %s, line %u\n",
711225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    level, "", (char *) readp, u128);
711325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (opcode == DW_MACINFO_undef)
711425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s#undef %s, line %u\n",
711525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    level, "", (char *) readp, u128);
711625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
711725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
711825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
711925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = endp + 1;
712025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
712125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
712225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_start_file:
712325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The two parameters are line and file index, in this order.  */
712403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (u128, readp, readendp);
712503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (readendp - readp < 1)
712603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
712703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf (gettext ("\
712803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes%*s*** missing DW_MACINFO_start_file argument at end of section"),
712903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      level, "");
713003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      return;
713103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
713203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_uleb128 (u128_2, readp, readendp);
713325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
713425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Find the CU DIE for this file.  */
713525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t macoff = readp - (const unsigned char *) data->d_buf;
713625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *fname = "???";
713725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (macoff >= cus[0].offset)
713825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
713925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      while (macoff >= cus[1].offset)
714025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		++cus;
714125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
714225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (cus[0].files == NULL
714325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
714425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		cus[0].files = (Dwarf_Files *) -1l;
714525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
714625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (cus[0].files != (Dwarf_Files *) -1l)
714725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
714825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ?: "???");
714925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
715025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
715125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*sstart_file %u, [%u] %s\n",
715225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  level, "", u128, u128_2, fname);
715325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++level;
715425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
715525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
715625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_MACINFO_end_file:
715725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  --level;
715825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*send_file\n", level, "");
715925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Nothing more to do.  */
716025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
716125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
716225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
716325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX gcc seems to generate files with a trailing zero.
716425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (opcode != 0 || readp != readendp))
716525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
716625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
716725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
716825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
716925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
717025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
717125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
717203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
717303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
717403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   Ebl *ebl, GElf_Ehdr *ehdr,
717503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
717603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
717703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  printf (gettext ("\
717803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
717903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
718003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  (uint64_t) shdr->sh_offset);
718103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  putc_unlocked ('\n', stdout);
718203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
718303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = dbg->sectiondata[IDX_debug_macro];
718403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (unlikely (data == NULL || data->d_buf == NULL))
718503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
718603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      error (0, 0, gettext ("cannot get macro information section data: %s"),
718703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	     elf_errmsg (-1));
718803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
718903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
719003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
719103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Get the source file information for all CUs.  Uses same
719203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     datastructure as macinfo.  But uses offset field to directly
719303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     match .debug_line offset.  And just stored in a list.  */
719403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Off offset;
719503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwarf_Off ncu = 0;
719603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t hsize;
719703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct mac_culist *culist = NULL;
719803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t nculist = 0;
719903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
720003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
720103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Die cudie;
720203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
720303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
720403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
720503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Attribute attr;
720603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
720703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
720803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
720903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Word lineoff;
721003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwarf_formudata (&attr, &lineoff) != 0)
721103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
721203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
721303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
721403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      newp->die = cudie;
721503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      newp->offset = lineoff;
721603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      newp->files = NULL;
721703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      newp->next = culist;
721803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      culist = newp;
721903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ++nculist;
722003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
722103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
722203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const unsigned char *readp = (const unsigned char *) data->d_buf;
722303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const unsigned char *readendp = readp + data->d_size;
722403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
722503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (readp < readendp)
722603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
722703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" Offset:             0x%" PRIx64 "\n"),
722803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      (uint64_t) (readp - (const unsigned char *) data->d_buf));
722903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
723003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
723103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      // optional vendor extension macro entry table.
723203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp + 2 > readendp)
723303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
723403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	invalid_data:
723503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  error (0, 0, gettext ("invalid data"));
723603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return;
723703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
723803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
723903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" Version:            %" PRIu16 "\n"), vers);
724003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
724103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
724203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      // 5 when it gets standardized.
724303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (vers != 4)
724403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
724503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf (gettext ("  unknown version, cannot parse section\n"));
724603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return;
724703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
724803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
724903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp + 1 > readendp)
725003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
725103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const unsigned char flag = *readp++;
725203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" Flag:               0x%" PRIx8 "\n"), flag);
725303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
725403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      unsigned int offset_len = (flag & 0x01) ? 8 : 4;
725503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf (gettext (" Offset length:      %" PRIu8 "\n"), offset_len);
725603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwarf_Off line_offset = -1;
725703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (flag & 0x02)
725803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
725903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (offset_len == 8)
726003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    line_offset = read_8ubyte_unaligned_inc (dbg, readp);
726103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  else
726203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    line_offset = read_4ubyte_unaligned_inc (dbg, readp);
726303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"),
726403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  line_offset);
726503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
726603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
726703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
726803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      memset (vendor, 0, sizeof vendor);
726903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (flag & 0x04)
727003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
727103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  // 1 byte length, for each item, 1 byte opcode, uleb128 number
727203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  // of arguments, for each argument 1 byte form code.
727303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (readp + 1 > readendp)
727403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_data;
727503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  unsigned int tlen = *readp++;
727603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf (gettext ("  extension opcode table, %" PRIu8 " items:\n"),
727703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  tlen);
727803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  for (unsigned int i = 0; i < tlen; i++)
727903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
728003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (readp + 1 > readendp)
728103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
728203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      unsigned int opcode = *readp++;
728303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf (gettext ("    [%" PRIx8 "]"), opcode);
728403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (opcode < DW_MACRO_GNU_lo_user
728503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  || opcode > DW_MACRO_GNU_hi_user)
728603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
728703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      // Record the start of description for this vendor opcode.
728803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      // uleb128 nr args, 1 byte per arg form.
728903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      vendor[opcode - DW_MACRO_GNU_lo_user] = readp;
729003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (readp + 1 > readendp)
729103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
729203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      unsigned int args = *readp++;
729303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (args > 0)
729403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		{
729503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  printf (gettext (" %" PRIu8 " arguments:"), args);
729603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  while (args > 0)
729703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    {
729803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 1 > readendp)
729903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
730003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      unsigned int form = *readp++;
730103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %s", dwarf_form_string (form));
730203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (form != DW_FORM_data1
730303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_data2
730403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_data4
730503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_data8
730603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_sdata
730703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_udata
730803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_block
730903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_block1
731003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_block2
731103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_block4
731203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_flag
731303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_string
731403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_strp
731503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && form != DW_FORM_sec_offset)
731603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
731703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      args--;
731803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (args > 0)
731903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			putchar_unlocked (',');
732003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    }
732103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		}
732203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else
732303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf (gettext (" no arguments."));
732403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      putchar_unlocked ('\n');
732503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
732603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
732703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      putchar_unlocked ('\n');
732803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
732903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      int level = 1;
733003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (readp + 1 > readendp)
733103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto invalid_data;
733203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      unsigned int opcode = *readp++;
733303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      while (opcode != 0)
733403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
733503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  unsigned int u128;
733603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  unsigned int u128_2;
733703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  const unsigned char *endp;
733803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  uint64_t off;
733903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
734003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes          switch (opcode)
734103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes            {
734203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes            case DW_MACRO_GNU_start_file:
734303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (u128, readp, readendp);
734403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (readp >= readendp)
734503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
734603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (u128_2, readp, readendp);
734703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
734803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      /* Find the CU DIE that matches this line offset.  */
734903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      const char *fname = "???";
735003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (line_offset != (Dwarf_Off) -1)
735103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		{
735203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  struct mac_culist *cu = culist;
735303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  while (cu != NULL && line_offset != cu->offset)
735403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    cu = cu->next;
735503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  if (cu != NULL)
735603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    {
735703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (cu->files == NULL
735803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  && dwarf_getsrcfiles (&cu->die, &cu->files,
735903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						NULL) != 0)
736003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			cu->files = (Dwarf_Files *) -1l;
736103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
736203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (cu->files != (Dwarf_Files *) -1l)
736303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			fname = (dwarf_filesrc (cu->files, u128_2,
736403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						NULL, NULL) ?: "???");
736503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    }
736603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		}
736703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*sstart_file %u, [%u] %s\n",
736803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      level, "", u128, u128_2, fname);
736903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      ++level;
737003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
737103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
737203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    case DW_MACRO_GNU_end_file:
737303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      --level;
737403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*send_file\n", level, "");
737503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
737603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
737703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    case DW_MACRO_GNU_define:
737803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (u128, readp, readendp);
737903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      endp = memchr (readp, '\0', readendp - readp);
738003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (endp == NULL)
738103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
738203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*s#define %s, line %u\n",
738303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      level, "", readp, u128);
738403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      readp = endp + 1;
738503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
738603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
738703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    case DW_MACRO_GNU_undef:
738803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (u128, readp, readendp);
738903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      endp = memchr (readp, '\0', readendp - readp);
739003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (endp == NULL)
739103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
739203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*s#undef %s, line %u\n",
739303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      level, "", readp, u128);
739403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      readp = endp + 1;
739503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
739603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
739703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    case DW_MACRO_GNU_define_indirect:
739803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (u128, readp, readendp);
739903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (readp + offset_len > readendp)
740003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
740103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (offset_len == 8)
740203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		off = read_8ubyte_unaligned_inc (dbg, readp);
740303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else
740403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		off = read_4ubyte_unaligned_inc (dbg, readp);
740503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*s#define %s, line %u (indirect)\n",
740603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      level, "", dwarf_getstring (dbg, off, NULL), u128);
740703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
740803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
740903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    case DW_MACRO_GNU_undef_indirect:
741003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      get_uleb128 (u128, readp, readendp);
741103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (readp + offset_len > readendp)
741203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
741303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (offset_len == 8)
741403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		off = read_8ubyte_unaligned_inc (dbg, readp);
741503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else
741603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		off = read_4ubyte_unaligned_inc (dbg, readp);
741703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*s#undef %s, line %u (indirect)\n",
741803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      level, "", dwarf_getstring (dbg, off, NULL), u128);
741903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
742003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
742103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    case DW_MACRO_GNU_transparent_include:
742203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (readp + offset_len > readendp)
742303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
742403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (offset_len == 8)
742503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		off = read_8ubyte_unaligned_inc (dbg, readp);
742603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else
742703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		off = read_4ubyte_unaligned_inc (dbg, readp);
742803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*s#include offset 0x%" PRIx64 "\n",
742903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      level, "", off);
743003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
743103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
743203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    default:
743303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
743403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (opcode < DW_MACRO_GNU_lo_user
743503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  || opcode > DW_MACRO_GNU_lo_user
743603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL)
743703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
743803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
743903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      const unsigned char *op_desc;
744003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      op_desc = vendor[opcode - DW_MACRO_GNU_lo_user];
744103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
744203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      // Just skip the arguments, we cannot really interpret them,
744303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      // but print as much as we can.
744403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      unsigned int args = *op_desc++;
744503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      while (args > 0)
744603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		{
744703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  unsigned int form = *op_desc++;
744803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  Dwarf_Word val;
744903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  switch (form)
745003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    {
745103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_data1:
745203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 1 > readendp)
745303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
745403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val = *readp++;
745503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %" PRIx8, (unsigned int) val);
745603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
745703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
745803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_data2:
745903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 2 > readendp)
746003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
746103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val = read_2ubyte_unaligned_inc (dbg, readp);
746203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf(" %" PRIx16, (unsigned int) val);
746303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
746403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
746503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_data4:
746603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 4 > readendp)
746703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
746803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val = read_4ubyte_unaligned_inc (dbg, readp);
746903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %" PRIx32, (unsigned int) val);
747003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
747103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
747203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_data8:
747303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 8 > readendp)
747403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
747503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val = read_8ubyte_unaligned_inc (dbg, readp);
747603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %" PRIx64, val);
747703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
747803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
747903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_sdata:
748003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      get_sleb128 (val, readp, readendp);
748103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %" PRIx64, val);
748203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
748303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
748403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_udata:
748503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      get_uleb128 (val, readp, readendp);
748603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %" PRIx64, val);
748703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
748803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
748903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_block:
749003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      get_uleb128 (val, readp, readendp);
749103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" block[%" PRIu64 "]", val);
749203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + val > readendp)
749303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
749403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      readp += val;
749503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
749603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
749703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_block1:
749803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 1 > readendp)
749903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
750003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val = *readp++;
750103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" block[%" PRIu64 "]", val);
750203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + val > readendp)
750303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
750403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
750503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
750603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_block2:
750703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 2 > readendp)
750803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
750903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val = read_2ubyte_unaligned_inc (dbg, readp);
751003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" block[%" PRIu64 "]", val);
751103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + val > readendp)
751203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
751303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
751403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
751503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_block4:
751603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 2 > readendp)
751703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
751803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val =read_4ubyte_unaligned_inc (dbg, readp);
751903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" block[%" PRIu64 "]", val);
752003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + val > readendp)
752103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
752203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
752303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
752403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_flag:
752503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + 1 > readendp)
752603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
752703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      val = *readp++;
752803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR));
752903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
753003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
753103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_string:
753203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      endp = memchr (readp, '\0', readendp - readp);
753303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (endp == NULL)
753403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
753503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %s", readp);
753603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      readp = endp + 1;
753703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
753803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
753903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_strp:
754003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + offset_len > readendp)
754103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
754203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (offset_len == 8)
754303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			val = read_8ubyte_unaligned_inc (dbg, readp);
754403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      else
754503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			val = read_4ubyte_unaligned_inc (dbg, readp);
754603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %s", dwarf_getstring (dbg, val, NULL));
754703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
754803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
754903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case DW_FORM_sec_offset:
755003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (readp + offset_len > readendp)
755103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			goto invalid_data;
755203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      if (offset_len == 8)
755303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			val = read_8ubyte_unaligned_inc (dbg, readp);
755403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      else
755503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			val = read_4ubyte_unaligned_inc (dbg, readp);
755603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf (" %" PRIx64, val);
755703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
755803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
755903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      default:
756003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			error (0, 0, gettext ("vendor opcode not verified?"));
756103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			return;
756203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    }
756303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
756403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  args--;
756503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  if (args > 0)
756603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    putchar_unlocked (',');
756703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		}
756803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      putchar_unlocked ('\n');
756903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
757003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
757103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (readp + 1 > readendp)
757203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto invalid_data;
757303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  opcode = *readp++;
757403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (opcode == 0)
757503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    putchar_unlocked ('\n');
757603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
757703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
757803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
757903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
758003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
758125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Callback for printing global names.  */
758225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
758325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
758425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		void *arg)
758525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
758625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int *np = (int *) arg;
758725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
758825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" [%5d] DIE offset: %6" PRId64
758925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
759025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (*np)++, global->die_offset, global->cu_offset, global->name);
759125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
759225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
759325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
759425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
759525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
759625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
759725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
759825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
759925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      Ebl *ebl, GElf_Ehdr *ehdr,
760025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
760125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
760225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
760325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
760425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset);
760525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
760625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int n = 0;
760725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
760825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
760925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
761025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the DWARF string section '.debug_str'.  */
761125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
761225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
761325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Ebl *ebl, GElf_Ehdr *ehdr,
761425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
761525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
761603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ?
761703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			  dbg->sectiondata[IDX_debug_str]->d_size : 0);
761825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
761925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Compute floor(log16(shdr->sh_size)).  */
762025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr tmp = sh_size;
762125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int digits = 1;
762225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (tmp >= 16)
762325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
762425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++digits;
762525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      tmp >>= 4;
762625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
762725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  digits = MAX (4, digits);
762825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
762925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
763025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " %*s  String\n"),
763125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn),
763225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
763325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* TRANS: the debugstr| prefix makes the string unique.  */
763425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  digits + 2, sgettext ("debugstr|Offset"));
763525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
763625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Off offset = 0;
763725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (offset < sh_size)
763825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
763925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t len;
764025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *str = dwarf_getstring (dbg, offset, &len);
764125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (str == NULL))
764225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
764325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext (" *** error while reading strings: %s\n"),
764425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  dwarf_errmsg (-1));
764525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
764625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
764725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
764825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
764925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
765025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += len + 1;
765125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
765225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
765325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
765425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
765525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the call frame search table section
765625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   '.eh_frame_hdr'.  */
765725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
765825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
765925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       Ebl *ebl __attribute__ ((unused)),
766025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       GElf_Ehdr *ehdr __attribute__ ((unused)),
766125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
766225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
766325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
766425b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
766525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn));
766625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
766725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
766825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
766925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
767025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
767125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
767225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ".eh_frame_hdr", elf_errmsg (-1));
767325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
767425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
767525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
767625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
767725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = ((unsigned char *) data->d_buf
767825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					+ data->d_size);
767925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
768025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
768125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
768225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid_data:
768325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("invalid data"));
768425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
768525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
768625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
768725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int version = *readp++;
768825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int eh_frame_ptr_enc = *readp++;
768925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int fde_count_enc = *readp++;
769025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int table_enc = *readp++;
769125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
769225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (" version:          %u\n"
769325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  " eh_frame_ptr_enc: %#x ",
769425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  version, eh_frame_ptr_enc);
769525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", eh_frame_ptr_enc);
769625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (" fde_count_enc:    %#x ", fde_count_enc);
769725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", fde_count_enc);
769825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (" table_enc:        %#x ", table_enc);
769925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", table_enc);
770025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
770125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint64_t eh_frame_ptr = 0;
770225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (eh_frame_ptr_enc != DW_EH_PE_omit)
770325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
770425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
770525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    dbg);
770625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (readp == NULL))
770725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
770825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
770925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
771025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
771125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (" (offset: %#" PRIx64 ")",
771225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* +4 because of the 4 byte header of the section.  */
771325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
771425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
771525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar_unlocked ('\n');
771625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
771725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
771825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint64_t fde_count = 0;
771925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fde_count_enc != DW_EH_PE_omit)
772025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
772125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
772225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (readp == NULL))
772325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto invalid_data;
772425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
772525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" fde_count:        %" PRIu64 "\n", fde_count);
772625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
772725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
772825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fde_count == 0 || table_enc == DW_EH_PE_omit)
772925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
773025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
773125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  puts (" Table:");
773225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
773325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Optimize for the most common case.  */
773425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
773525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (fde_count > 0 && readp + 8 <= dataend)
773625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
773725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
773825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	uint64_t initial_offset = ((uint64_t) shdr->sh_offset
773925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   + (int64_t) initial_location);
774025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
774125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	// XXX Possibly print symbol name or section offset for initial_offset
774225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
774325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		" fde=[%6" PRIx64 "]\n",
774425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		initial_location, initial_offset,
774525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		address, address - (eh_frame_ptr + 4));
774625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
774725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
774825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (0 && readp < dataend)
774925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
775025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
775125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
775225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
775325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
775425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
775525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the exception handling table section
775625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   '.eh_frame_hdr'.  */
775725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
775825b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
775925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Ebl *ebl __attribute__ ((unused)),
776025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     GElf_Ehdr *ehdr __attribute__ ((unused)),
776125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Elf_Scn *scn,
776225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     GElf_Shdr *shdr __attribute__ ((unused)),
776325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     Dwarf *dbg __attribute__ ((unused)))
776425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
776525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\
776625b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nException handling table section [%2zu] '.gcc_except_table':\n"),
776725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn));
776825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
776925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
777025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
777125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
777225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
777325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
777425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ".gcc_except_table", elf_errmsg (-1));
777525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
777625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
777725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
777825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
777925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = readp + data->d_size;
778025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
778125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 1 > dataend))
778225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
778325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid_data:
778425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("invalid data"));
778525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
778625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
778725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int lpstart_encoding = *readp++;
778825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" LPStart encoding:    %#x "), lpstart_encoding);
778925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", lpstart_encoding);
779025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (lpstart_encoding != DW_EH_PE_omit)
779125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
779225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t lpstart;
779325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
779425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" LPStart:             %#" PRIx64 "\n", lpstart);
779525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
779625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
779725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 1 > dataend))
779825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
779925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int ttype_encoding = *readp++;
780025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" TType encoding:      %#x "), ttype_encoding);
780125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", ttype_encoding);
780225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *ttype_base = NULL;
780325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ttype_encoding != DW_EH_PE_omit)
780425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
780525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int ttype_base_offset;
780603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      get_uleb128 (ttype_base_offset, readp, dataend);
780725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" TType base offset:   %#x\n", ttype_base_offset);
780803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if ((size_t) (dataend - readp) > ttype_base_offset)
780903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes        ttype_base = readp + ttype_base_offset;
781025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
781125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
781225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 1 > dataend))
781325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
781425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int call_site_encoding = *readp++;
781525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
781625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  print_encoding_base ("", call_site_encoding);
781725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int call_site_table_len;
781803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  get_uleb128 (call_site_table_len, readp, dataend);
781925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
782025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const action_table = readp + call_site_table_len;
782125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (action_table > dataend))
782225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
782325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int u = 0;
782425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int max_action = 0;
782525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (readp < action_table)
782625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
782725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (u == 0)
782825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	puts (gettext ("\n Call site table:"));
782925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
783025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t call_site_start;
783125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (call_site_encoding, readp, dataend,
783225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    &call_site_start, dbg);
783325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t call_site_length;
783425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (call_site_encoding, readp, dataend,
783525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    &call_site_length, dbg);
783625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t landing_pad;
783725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp = read_encoded (call_site_encoding, readp, dataend,
783825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    &landing_pad, dbg);
783925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int action;
784003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      get_uleb128 (action, readp, dataend);
784125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      max_action = MAX (action, max_action);
784225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
784325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "        Call site length:  %" PRIu64 "\n"
784425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "        Landing pad:       %#" PRIx64 "\n"
784525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       "        Action:            %u\n"),
784625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      u++, call_site_start, call_site_length, landing_pad, action);
784725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
784803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (readp != action_table)
784903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    goto invalid_data;
785025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
785125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int max_ar_filter = 0;
785225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (max_action > 0)
785325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
785425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts ("\n Action table:");
785525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
785603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if ((size_t) (dataend - action_table) < max_action + 1)
785703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
785803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  fputs (gettext ("   <INVALID DATA>\n"), stdout);
785903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return;
786003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
786103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
786225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned char *const action_table_end
786325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	= action_table + max_action + 1;
786425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
786525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      u = 0;
786625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
786725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
786825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int ar_filter;
786903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_sleb128 (ar_filter, readp, action_table_end);
787025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
787125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    max_ar_filter = ar_filter;
787225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int ar_disp;
787303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  get_sleb128 (ar_disp, readp, action_table_end);
787425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
787525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%4u] ar_filter:  % d\n"
787625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  "        ar_disp:    % -5d",
787725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  u, ar_filter, ar_disp);
787825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (abs (ar_disp) & 1)
787925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
788025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (ar_disp != 0)
788125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    puts (" -> ???");
788225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
788325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    putchar_unlocked ('\n');
788425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++u;
788525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
788625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (readp < action_table_end);
788725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
788825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
788903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (max_ar_filter > 0 && ttype_base != NULL)
789025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
789125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      puts ("\n TType table:");
789225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
789325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      // XXX Not *4, size of encoding;
789425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (ttype_encoding & 7)
789525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
789625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_udata2:
789725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_sdata2:
789825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = ttype_base - max_ar_filter * 2;
789925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
790025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_udata4:
790125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_sdata4:
790225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = ttype_base - max_ar_filter * 4;
790325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
790425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_udata8:
790525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_EH_PE_sdata8:
790625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = ttype_base - max_ar_filter * 8;
790725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
790825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
790925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (1, 0, gettext ("invalid TType encoding"));
791025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
791125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
791225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
791325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
791425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint64_t ttype;
791525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
791625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				dbg);
791725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
791825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
791925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (readp < ttype_base);
792025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
792125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
792225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
792325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the content of the '.gdb_index' section.
792425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
792525b3c049e70834cf33790a28643ab058b507b35cBen Cheng*/
792625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
792725b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
792825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
792925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
793025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
793125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %" PRId64 " bytes :\n"),
793225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
793325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
793425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
793525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
793625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
793725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (data == NULL))
793825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
793925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("cannot get %s content: %s"),
794025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     ".gdb_index", elf_errmsg (-1));
794125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
794225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
794325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
794425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  // .gdb_index is always in little endian.
794525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
794625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  dbg = &dummy_dbg;
794725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
794825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *readp = data->d_buf;
794925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *const dataend = readp + data->d_size;
795025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
795125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
795225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
795325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    invalid_data:
795425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("invalid data"));
795525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
795625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
795725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
795825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int32_t vers = read_4ubyte_unaligned (dbg, readp);
795925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" Version:         %" PRId32 "\n"), vers);
796025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
796125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  // The only difference between version 4 and version 5 is the
796203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  // hash used for generating the table.  Version 6 contains symbols
796303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  // for inlined functions, older versions didn't.  Version 7 adds
796403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  // symbol kinds.  Version 8 just indicates that it correctly includes
796503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  // TUs for symbols.
796603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (vers < 4 || vers > 8)
796725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
796825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  unknown version, cannot parse section\n"));
796925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
797025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
797125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
797225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
797325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
797425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
797525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
797625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
797725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" CU offset:       %#" PRIx32 "\n"), cu_off);
797825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
797925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
798025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
798125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
798225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
798325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
798425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" TU offset:       %#" PRIx32 "\n"), tu_off);
798525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
798625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
798725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
798825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
798925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
799025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
799125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" address offset:  %#" PRIx32 "\n"), addr_off);
799225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
799325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
799425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
799525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
799625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
799725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
799825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" symbol offset:   %#" PRIx32 "\n"), sym_off);
799925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
800025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp += 4;
800125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (readp + 4 > dataend))
800225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto invalid_data;
800325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
800425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
800525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext (" constant offset: %#" PRIx32 "\n"), const_off);
800625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
800725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + cu_off;
800825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
800925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *nextp = data->d_buf + tu_off;
801003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t cu_nr = (nextp - readp) / 16;
801125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
801225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n CU list at offset %#" PRIx32
801325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu entries:\n"),
801403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  cu_off, cu_nr);
801525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
801625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t n = 0;
801703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (readp + 16 <= dataend && n < cu_nr)
801825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
801925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t off = read_8ubyte_unaligned (dbg, readp);
802025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
802125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
802225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t len = read_8ubyte_unaligned (dbg, readp);
802325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
802425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
802525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%4zu] start: %0#8" PRIx64
802625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ", length: %5" PRIu64 "\n", n, off, len);
802725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
802825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
802925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
803025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + tu_off;
803125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nextp = data->d_buf + addr_off;
803203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t tu_nr = (nextp - readp) / 24;
803325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
803425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n TU list at offset %#" PRIx32
803525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu entries:\n"),
803603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  tu_off, tu_nr);
803725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
803825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  n = 0;
803903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (readp + 24 <= dataend && n < tu_nr)
804025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
804125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t off = read_8ubyte_unaligned (dbg, readp);
804225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
804325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
804425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t type = read_8ubyte_unaligned (dbg, readp);
804525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
804625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
804725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t sig = read_8ubyte_unaligned (dbg, readp);
804825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
804925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
805025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%4zu] CU offset: %5" PRId64
805125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ", type offset: %5" PRId64
805225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
805325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
805425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
805525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
805625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + addr_off;
805725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nextp = data->d_buf + sym_off;
805803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t addr_nr = (nextp - readp) / 20;
805925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
806025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n Address list at offset %#" PRIx32
806125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu entries:\n"),
806203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  addr_off, addr_nr);
806325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
806425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  n = 0;
806503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (readp + 20 <= dataend && n < addr_nr)
806625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
806725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t low = read_8ubyte_unaligned (dbg, readp);
806825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
806925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
807025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t high = read_8ubyte_unaligned (dbg, readp);
807125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 8;
807225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
807325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t idx = read_4ubyte_unaligned (dbg, readp);
807425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 4;
807525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
807603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      char *l = format_dwarf_addr (dwflmod, 8, low, low);
807703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      char *h = format_dwarf_addr (dwflmod, 8, high - 1, high);
807825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
807925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      n, l, h, idx);
808003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      free (l);
808103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      free (h);
808225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
808325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
808425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
808525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  readp = data->d_buf + sym_off;
808625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  nextp = data->d_buf + const_off;
808703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t sym_nr = (nextp - readp) / 8;
808825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
808925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\n Symbol table at offset %#" PRIx32
809025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   " contains %zu slots:\n"),
809103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  addr_off, sym_nr);
809225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
809325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  n = 0;
809403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (readp + 8 <= dataend && n < sym_nr)
809525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
809625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t name = read_4ubyte_unaligned (dbg, readp);
809725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 4;
809825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
809925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t vector = read_4ubyte_unaligned (dbg, readp);
810025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      readp += 4;
810125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
810225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (name != 0 || vector != 0)
810325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
810425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *sym = data->d_buf + const_off + name;
810503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (unlikely (sym > dataend
810603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			|| memchr (sym, '\0', dataend - sym) == NULL))
810725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
810825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
810925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (" [%4zu] symbol: %s, CUs: ", n, sym);
811025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
811125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const unsigned char *readcus = data->d_buf + const_off + vector;
811203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (unlikely (readcus + 4 > dataend))
811325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    goto invalid_data;
811425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
811525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (cus--)
811625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
811703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      uint32_t cu_kind, cu, kind;
811803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      bool is_static;
811925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      readcus += 4;
812003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (unlikely (readcus + 4 > dataend))
812103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		goto invalid_data;
812203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      cu_kind = read_4ubyte_unaligned (dbg, readcus);
812303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      cu = cu_kind & ((1 << 24) - 1);
812403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      kind = (cu_kind >> 28) & 7;
812503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      is_static = cu_kind & (1U << 31);
812603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (cu > cu_nr - 1)
812703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
812803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else
812903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf ("%" PRId32, cu);
813003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (kind != 0)
813103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		{
813203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  printf (" (");
813303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  switch (kind)
813403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    {
813503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case 1:
813603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf ("type");
813703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
813803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case 2:
813903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf ("var");
814003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
814103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case 3:
814203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf ("func");
814303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
814403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    case 4:
814503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf ("other");
814603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
814703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    default:
814803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      printf ("unknown-0x%" PRIx32, kind);
814903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      break;
815003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    }
815103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  printf (":%c)", (is_static ? 'S' : 'G'));
815203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		}
815303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      if (cus > 0)
815403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		printf (", ");
815525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
815625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("\n");
815725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
815825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      n++;
815925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
816025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
816125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
816225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
816325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
816425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
816525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Before we start the real work get a debug context descriptor.  */
816625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf_Addr dwbias;
816725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
816825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Dwarf dummy_dbg =
816925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
817025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .elf = ebl->elf,
817125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
817225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
817325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (dbg == NULL)
817425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
817525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((print_debug_sections & ~section_exception) != 0)
817625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get debug context descriptor: %s"),
817725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       dwfl_errmsg (-1));
817825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((print_debug_sections & section_exception) == 0)
817925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return;
818025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dbg = &dummy_dbg;
818125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
818225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
818325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
818425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
818525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
818625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
818725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
818825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
818925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Look through all the sections for the debugging sections to print.  */
819025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
819125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
819225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
819325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
819425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
819525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
819625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
819725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
819825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  static const struct
819925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
820025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    const char *name;
820125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    enum section_e bitmask;
820225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    void (*fp) (Dwfl_Module *, Ebl *,
820325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
820425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  } debug_sections[] =
820525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
820625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define NEW_SECTION(name) \
820725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".debug_" #name, section_##name, print_debug_##name##_section }
820825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (abbrev),
820925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (aranges),
821025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (frame),
821125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (info),
821225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (types),
821325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (line),
821425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (loc),
821525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (pubnames),
821625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (str),
821725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (macinfo),
821803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      NEW_SECTION (macro),
821925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      NEW_SECTION (ranges),
822025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".eh_frame", section_frame | section_exception,
822125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		print_debug_frame_section },
822225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".eh_frame_hdr", section_frame | section_exception,
822325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		print_debug_frame_hdr_section },
822425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".gcc_except_table", section_frame | section_exception,
822525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		print_debug_exception_table },
822625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      { ".gdb_index", section_gdb_index, print_gdb_index_section }
822725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    };
822825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const int ndebug_sections = (sizeof (debug_sections)
822925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       / sizeof (debug_sections[0]));
823025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *name = elf_strptr (ebl->elf, shstrndx,
823125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 shdr->sh_name);
823203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (name == NULL)
823303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    continue;
823425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
823503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  int n;
823625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (n = 0; n < ndebug_sections; ++n)
823725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (strcmp (name, debug_sections[n].name) == 0
823825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if USE_ZLIB
823925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		|| (name[0] == '.' && name[1] == 'z'
824025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && debug_sections[n].name[1] == 'd'
824125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && strcmp (&name[2], &debug_sections[n].name[1]) == 0)
824225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
824325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		)
824425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
824525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if ((print_debug_sections | implicit_debug_sections)
824625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    & debug_sections[n].bitmask)
824725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
824825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
824925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
825025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
825125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
825225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
825325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  reset_listptr (&known_loclistptr);
825425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  reset_listptr (&known_rangelistptr);
825525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
825625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
825725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
825825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ITEM_INDENT		4
825903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define WRAP_COLUMN		75
826003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
826103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Print "NAME: FORMAT", wrapping when output text would make the line
826203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   exceed WRAP_COLUMN.  Unpadded numbers look better for the core items
826303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   but this function is also used for registers which should be printed
826403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   aligned.  Fortunately registers output uses fixed fields width (such
826503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   as %11d) for the alignment.
826603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
826703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   Line breaks should not depend on the particular values although that
826803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   may happen in some cases of the core items.  */
826925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
827025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
827103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__attribute__ ((format (printf, 6, 7)))
827225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_core_item (unsigned int colno, char sep, unsigned int wrap,
827303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 size_t name_width, const char *name, const char *format, ...)
827425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
827525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t len = strlen (name);
827625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (name_width < len)
827725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    name_width = len;
827825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
827903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  char *out;
828003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  va_list ap;
828103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  va_start (ap, format);
828203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int out_len = vasprintf (&out, format, ap);
828303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  va_end (ap);
828403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (out_len == -1)
828503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0, _("memory exhausted"));
828603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
828703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t n = name_width + sizeof ": " - 1 + out_len;
828825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
828925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (colno == 0)
829025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
829125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%*s", ITEM_INDENT, "");
829225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = ITEM_INDENT + n;
829325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
829425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (colno + 2 + n < wrap)
829525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
829625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("%c ", sep);
829725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno += 2 + n;
829825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
829925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
830025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
830125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("\n%*s", ITEM_INDENT, "");
830225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      colno = ITEM_INDENT + n;
830325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
830425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
830503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
830625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
830703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  free (out);
830825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
830925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
831025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
831125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
831225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const void *
831325b3c049e70834cf33790a28643ab058b507b35cBen Chengconvert (Elf *core, Elf_Type type, uint_fast16_t count,
831425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 void *value, const void *data, size_t size)
831525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
831625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data valuedata =
831725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
831825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_type = type,
831925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_buf = value,
832025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
832125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_version = EV_CURRENT,
832225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
832325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data indata =
832425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
832525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_type = type,
832625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_buf = (void *) data,
832725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_size = valuedata.d_size,
832825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      .d_version = EV_CURRENT,
832925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    };
833025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
833125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
833225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 ? elf32_xlatetom : elf64_xlatetom)
833325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
833425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (d == NULL)
833525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
833625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
833725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
833825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return data + indata.d_size;
833925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
834025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
834125b3c049e70834cf33790a28643ab058b507b35cBen Chengtypedef uint8_t GElf_Byte;
834225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
834325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
834425b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
834525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  unsigned int colno, size_t *repeated_size)
834625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
834725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast16_t count = item->count ?: 1;
834825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
834925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define TYPES								      \
835003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8);			      \
835103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16);			      \
835203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32);			      \
835303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32);			      \
835403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64);			      \
835503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
835603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
835703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name[count]
835825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  union { TYPES; } value;
835925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
836025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
836125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *data = &value;
836225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
836325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t convsize = size;
836425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (repeated_size != NULL)
836525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
836625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
836725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
836825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data = alloca (*repeated_size);
836925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  count *= *repeated_size / size;
837025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  convsize = count * size;
837125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *repeated_size -= convsize;
837225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
837325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (item->count != 0 || item->format != '\n')
837425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*repeated_size -= size;
837525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
837625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
837725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  convert (core, item->type, count, data, desc + item->offset, convsize);
837825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
837925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Type type = item->type;
838025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (type == ELF_T_ADDR)
838125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
838225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
838325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (item->format)
838425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
838525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'd':
838625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 1);
838725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
838825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
838903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define DO_TYPE(NAME, Name, hex, dec)					      \
839025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case ELF_T_##NAME:						      \
839103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    colno = print_core_item (colno, ',', WRAP_COLUMN,		      \
839203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				     0, item->name, dec, value.Name[0]); \
839325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break
839425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  TYPES;
839525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
839625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
839725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  abort ();
839825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
839925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
840025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
840125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'x':
840225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 1);
840325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
840425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
840503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define DO_TYPE(NAME, Name, hex, dec)					      \
840625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case ELF_T_##NAME:						      \
840703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    colno = print_core_item (colno, ',', WRAP_COLUMN,		      \
840803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				     0, item->name, hex, value.Name[0]);      \
840925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break
841025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  TYPES;
841125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
841225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
841325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  abort ();
841425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
841525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
841625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
841725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'b':
841825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'B':
841925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (size % sizeof (unsigned int) == 0);
842025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int nbits = count * size * 8;
842125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned int pop = 0;
842225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
842325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	pop += __builtin_popcount (*i);
842425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool negate = pop > nbits / 2;
842525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const unsigned int bias = item->format == 'b';
842625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
842725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
842803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	char printed[(negate ? nbits - pop : pop) * 16 + 1];
842925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	char *p = printed;
843025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*p = '\0';
843125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
843225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
843325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
843425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    assert (size == sizeof (unsigned int) * 2);
843525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    for (unsigned int *i = data;
843625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 (void *) i < data + count * size; i += 2)
843725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
843825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		unsigned int w = i[1];
843925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		i[1] = i[0];
844025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		i[0] = w;
844125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
844225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
844325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
844425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	unsigned int lastbit = 0;
844503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	unsigned int run = 0;
844625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	for (const unsigned int *i = data;
844725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     (void *) i < data + count * size; ++i)
844825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
844925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    unsigned int bit = ((void *) i - data) * 8;
845025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    unsigned int w = negate ? ~*i : *i;
845125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (w != 0)
845225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
845325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		int n = ffs (w);
845425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		w >>= n;
845525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		bit += n;
845625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
845703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		if (lastbit != 0 && lastbit + 1 == bit)
845825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ++run;
845925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		else
846025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
846125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (lastbit == 0)
846225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      p += sprintf (p, "%u", bit - bias);
846325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else if (run == 0)
846425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      p += sprintf (p, ",%u", bit - bias);
846525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    else
846625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
846725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    run = 0;
846825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
846925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
847025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		lastbit = bit;
847125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
847225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
847303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
847403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  p += sprintf (p, "-%u", lastbit - bias);
847525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
847603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
847725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 negate ? "~<%s>" : "<%s>", printed);
847825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
847925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
848025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
848125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'T':
848225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case (char) ('T'|0x80):
848325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 2);
848425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word sec;
848525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Dwarf_Word usec;
848625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
848725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
848803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define DO_TYPE(NAME, Name, hex, dec)					      \
848925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case ELF_T_##NAME:						      \
849025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    sec = value.Name[0];					      \
849125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    usec = value.Name[1];					      \
849225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break
849325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  TYPES;
849425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DO_TYPE
849525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
849625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  abort ();
849725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
849825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (item->format == (char) ('T'|0x80)))
849925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
850025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This is a hack for an ill-considered 64-bit ABI where
850125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     tv_usec is actually a 32-bit field with 32 bits of padding
850225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     rounding out struct timeval.  We've already converted it as
850325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     a 64-bit field.  For little-endian, this just means the
850425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     high half is the padding; it's presumably zero, but should
850525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     be ignored anyway.  For big-endian, it means the 32-bit
850625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     field went into the high half of USEC.  */
850725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Ehdr ehdr_mem;
850825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
850925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
851025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    usec >>= 32;
851125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
851225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    usec &= UINT32_MAX;
851325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
851403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
851503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			       "%" PRIu64 ".%.6" PRIu64, sec, usec);
851625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
851725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
851825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'c':
851925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (count == 1);
852003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
852103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			       "%c", value.Byte[0]);
852225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
852325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
852425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 's':
852503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
852603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			       "%.*s", (int) count, value.Byte);
852725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
852825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
852925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case '\n':
853025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is a list of strings separated by '\n'.  */
853125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (item->count == 0);
853225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (repeated_size != NULL);
853325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (item->name == NULL);
853425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (item->offset >= *repeated_size))
853525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
853625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
853725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *s = desc + item->offset;
853825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size = *repeated_size - item->offset;
853925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *repeated_size = 0;
854025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (size > 0)
854125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
854225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *eol = memchr (s, '\n', size);
854325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int len = size;
854425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (eol != NULL)
854525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    len = eol - s;
854625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
854725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (eol == NULL)
854825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
854925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size -= eol + 1 - s;
855025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  s = eol + 1;
855125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
855225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
855303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      colno = WRAP_COLUMN;
855403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      break;
855503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
855603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    case 'h':
855725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
855825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
855925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
856025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, "XXX not handling format '%c' for %s",
856125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     item->format, item->name);
856225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
856325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
856425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
856525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef TYPES
856625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
856725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
856825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
856925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
857025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
857125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort items by group, and by layout offset within each group.  */
857225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
857325b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_core_items (const void *a, const void *b)
857425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
857525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *p1 = a;
857625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *p2 = b;
857725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item1 = *p1;
857825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item2 = *p2;
857925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
858025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return ((item1->group == item2->group ? 0
858125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   : strcmp (item1->group, item2->group))
858225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: (int) item1->offset - (int) item2->offset);
858325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
858425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
858525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort item groups by layout offset of the first item in the group.  */
858625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
858725b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_core_item_groups (const void *a, const void *b)
858825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
858925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *const *p1 = a;
859025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *const *p2 = b;
859125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *group1 = *p1;
859225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *const *group2 = *p2;
859325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item1 = *group1;
859425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *item2 = *group2;
859525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
859625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return (int) item1->offset - (int) item2->offset;
859725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
859825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
859925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
860025b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_items (Elf *core, const void *desc, size_t descsz,
860125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   const Ebl_Core_Item *items, size_t nitems)
860225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
860325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nitems == 0)
860425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 0;
860503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  unsigned int colno = 0;
860603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
860703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* FORMAT '\n' makes sense to be present only as a single item as it
860803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     processes all the data of a note.  FORMATs 'b' and 'B' have a special case
860903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     if present as a single item but they can be also processed with other
861003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     items below.  */
861103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
861203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		      || items[0].format == 'B'))
861303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
861403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      assert (items[0].offset == 0);
861503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      size_t size = descsz;
861603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      colno = handle_core_item (core, items, desc, colno, &size);
861703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* If SIZE is not zero here there is some remaining data.  But we do not
861803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 know how to process it anyway.  */
861903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return colno;
862003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
862103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (size_t i = 0; i < nitems; ++i)
862203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    assert (items[i].format != '\n');
862325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
862425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Sort to collect the groups together.  */
862525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *sorted_items[nitems];
862625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nitems; ++i)
862725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    sorted_items[i] = &items[i];
862825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
862925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
863025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Collect the unique groups and sort them.  */
863125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item **groups[nitems];
863225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  groups[0] = &sorted_items[0];
863325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t ngroups = 1;
863425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 1; i < nitems; ++i)
863525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (sorted_items[i]->group != sorted_items[i - 1]->group
863625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
863725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      groups[ngroups++] = &sorted_items[i];
863825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
863925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
864025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out all the groups.  */
864125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const void *last = desc;
864225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
864325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
864425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < ngroups; ++i)
864525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
864625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (const Ebl_Core_Item **item = groups[i];
864725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       (item < &sorted_items[nitems]
864825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& ((*item)->group == groups[i][0]->group
864925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    || !strcmp ((*item)->group, groups[i][0]->group)));
865025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       ++item)
865125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    colno = handle_core_item (core, *item, desc, colno, NULL);
865225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
865325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Force a line break at the end of the group.  */
865403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  colno = WRAP_COLUMN;
865525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
865625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
865725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (descsz == 0)
865825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
865925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
866025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This set of items consumed a certain amount of the note's data.
866125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 If there is more data there, we have another unit of the same size.
866225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 Loop to print that out too.  */
866325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const Ebl_Core_Item *item = &items[nitems - 1];
866425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t eltsz = item->offset + gelf_fsize (core, item->type,
866525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						item->count ?: 1, EV_CURRENT);
866625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
866725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int reps = -1;
866825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
866925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
867025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++reps;
867125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  desc += eltsz;
867225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  descsz -= eltsz;
867325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
867425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (descsz >= eltsz && !memcmp (desc, last, eltsz));
867525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
867625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (reps == 1)
867725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
867825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* For just one repeat, print it unabridged twice.  */
867925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  desc -= eltsz;
868025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  descsz += eltsz;
868125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
868225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (reps > 1)
868325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext ("\n%*s... <repeats %u more times> ..."),
868425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		ITEM_INDENT, "", reps);
868525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
868625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      last = desc;
868725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
868825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (descsz > 0);
868925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
869025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
869125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
869225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
869325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
869425b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
869525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      unsigned int colno)
869625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
869725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  desc += regloc->offset;
869825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
869925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  abort ();			/* XXX */
870025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
870125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
870225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
870325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
870425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
870525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_register (Ebl *ebl, Elf *core, int maxregname,
870625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      const Ebl_Register_Location *regloc, const void *desc,
870725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      unsigned int colno)
870825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
870925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (regloc->bits % 8 != 0)
871025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return handle_bit_registers (regloc, desc, colno);
871125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
871225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  desc += regloc->offset;
871325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
871425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
871525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
871625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char name[REGNAMESZ];
871725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int bits;
871825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int type;
871925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      register_info (ebl, reg, regloc, name, &bits, &type);
872025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
872125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define TYPES								      \
872203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8);			      \
872303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16);			      \
872403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32);			      \
872503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64)
872625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
872703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define BITS(bits, xtype, sfmt, ufmt)				\
872825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint##bits##_t b##bits; int##bits##_t b##bits##s
872925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      union { TYPES; uint64_t b128[2]; } value;
873025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef	BITS
873125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
873225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (type)
873325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
873425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_ATE_unsigned:
873525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_ATE_signed:
873625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case DW_ATE_address:
873725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  switch (bits)
873825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
873903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define BITS(bits, xtype, sfmt, ufmt)					      \
874025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    case bits:							      \
874125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
874225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (type == DW_ATE_signed)				      \
874303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		colno = print_core_item (colno, ' ', WRAP_COLUMN,	      \
874425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 maxregname, name,		      \
874503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					 sfmt, value.b##bits##s);	      \
874625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else							      \
874703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		colno = print_core_item (colno, ' ', WRAP_COLUMN,	      \
874825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 maxregname, name,		      \
874903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					 ufmt, value.b##bits);		      \
875025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break
875125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
875225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    TYPES;
875325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
875425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    case 128:
875525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert (type == DW_ATE_unsigned);
875625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
875725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
875803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      colno = print_core_item (colno, ' ', WRAP_COLUMN,
875925b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       maxregname, name,
876003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				       "0x%.16" PRIx64 "%.16" PRIx64,
876125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       value.b128[!be], value.b128[be]);
876225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      break;
876325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
876425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    default:
876525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      abort ();
876625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef	BITS
876725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
876825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
876925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
877025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
877125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Print each byte in hex, the whole thing in native byte order.  */
877225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (bits % 8 == 0);
877325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const uint8_t *bytes = desc;
877425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  desc += bits / 8;
877525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char hex[bits / 4 + 1];
877625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  hex[bits / 4] = '\0';
877725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int incr = 1;
877825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
877925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
878025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bytes += bits / 8 - 1;
878125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      incr = -1;
878225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
878325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t idx = 0;
878425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
878525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
878625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
878725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
878825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
878903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  colno = print_core_item (colno, ' ', WRAP_COLUMN,
879003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				   maxregname, name, "0x%s", hex);
879125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
879225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
879325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      desc += regloc->pad;
879425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
879525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef TYPES
879625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
879725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
879825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
879925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
880025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
880125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
880225b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct register_info
880325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
880425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Register_Location *regloc;
880525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *set;
880625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char name[REGNAMESZ];
880725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int regno;
880825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int bits;
880925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int type;
881025b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
881125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
881225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
881325b3c049e70834cf33790a28643ab058b507b35cBen Chengregister_bitpos (const struct register_info *r)
881425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
881525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return (r->regloc->offset * 8
881625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  + ((r->regno - r->regloc->regno)
881725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     * (r->regloc->bits + r->regloc->pad * 8)));
881825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
881925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
882025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
882125b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_sets_by_info (const struct register_info *r1,
882225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      const struct register_info *r2)
882325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
882425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return ((int) r2->bits - (int) r1->bits
882525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: register_bitpos (r1) - register_bitpos (r2));
882625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
882725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
882825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort registers by set, and by size and layout offset within each set.  */
882925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
883025b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_registers (const void *a, const void *b)
883125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
883225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *r1 = a;
883325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *r2 = b;
883425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
883525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Unused elements sort last.  */
883625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (r1->regloc == NULL)
883725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return r2->regloc == NULL ? 0 : 1;
883825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (r2->regloc == NULL)
883925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
884025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
884125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
884225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ?: compare_sets_by_info (r1, r2));
884325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
884425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
884525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Sort register sets by layout offset of the first register in the set.  */
884625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
884725b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_register_sets (const void *a, const void *b)
884825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
884925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *const *p1 = a;
885025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const struct register_info *const *p2 = b;
885125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return compare_sets_by_info (*p1, *p2);
885225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
885325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
885425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned int
885525b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_registers (Ebl *ebl, Elf *core, const void *desc,
885625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       const Ebl_Register_Location *reglocs, size_t nregloc)
885725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
885825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (nregloc == 0)
885925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 0;
886025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
886125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
886225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (maxnreg <= 0)
886325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
886425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < nregloc; ++i)
886525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (maxnreg < reglocs[i].regno + reglocs[i].count)
886625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  maxnreg = reglocs[i].regno + reglocs[i].count;
886725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (maxnreg > 0);
886825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
886925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
887025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct register_info regs[maxnreg];
887125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memset (regs, 0, sizeof regs);
887225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
887325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Sort to collect the sets together.  */
887425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int maxreg = 0;
887525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nregloc; ++i)
887625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    for (int reg = reglocs[i].regno;
887725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 reg < reglocs[i].regno + reglocs[i].count;
887825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 ++reg)
887925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
888025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	assert (reg < maxnreg);
888125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (reg > maxreg)
888225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  maxreg = reg;
888325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	struct register_info *info = &regs[reg];
888425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	info->regloc = &reglocs[i];
888525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	info->regno = reg;
888625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	info->set = register_info (ebl, reg, &reglocs[i],
888725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   info->name, &info->bits, &info->type);
888825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
888925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
889025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
889125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Collect the unique sets and sort them.  */
889225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  inline bool same_set (const struct register_info *a,
889325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const struct register_info *b)
889425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
889525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (a < &regs[maxnreg] && a->regloc != NULL
889625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    && b < &regs[maxnreg] && b->regloc != NULL
889725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    && a->bits == b->bits
889825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    && (a->set == b->set || !strcmp (a->set, b->set)));
889925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
890025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct register_info *sets[maxreg + 1];
890125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  sets[0] = &regs[0];
890225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nsets = 1;
890325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int i = 1; i <= maxreg; ++i)
890425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
890525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      sets[nsets++] = &regs[i];
890625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
890725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
890825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out all the sets.  */
890925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int colno = 0;
891025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nsets; ++i)
891125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
891225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Find the longest name of a register in this set.  */
891325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t maxname = 0;
891425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const struct register_info *end;
891525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (end = sets[i]; same_set (sets[i], end); ++end)
891625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
891725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t len = strlen (end->name);
891825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (len > maxname)
891925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    maxname = len;
892025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
892125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
892225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (const struct register_info *reg = sets[i];
892325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   reg < end;
892425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   reg += reg->regloc->count ?: 1)
892525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	colno = handle_core_register (ebl, core, maxname,
892625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      reg->regloc, desc, colno);
892725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
892825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Force a line break at the end of the group.  */
892903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      colno = WRAP_COLUMN;
893025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
893125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
893225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return colno;
893325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
893425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
893525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
893625b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
893725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
893825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
893925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
894025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_error:
894125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
894225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
894325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
894425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
894525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t i = 0; i < nauxv; ++i)
894625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
894725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_auxv_t av_mem;
894825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
894925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (av == NULL)
895025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto elf_error;
895125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
895225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *name;
895325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *fmt;
895425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
895525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
895625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Unknown type.  */
895725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (av->a_un.a_val == 0)
895825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %" PRIu64 "\n", av->a_type);
895925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
896025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
896125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    av->a_type, av->a_un.a_val);
896225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
896325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
896425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	switch (fmt[0])
896525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
896625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case '\0':		/* Normally zero.  */
896725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (av->a_un.a_val == 0)
896825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
896925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("    %s\n", name);
897025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
897125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
897225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Fall through */
897325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'x':		/* hex */
897425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'p':		/* address */
897525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 's':		/* address of string */
897625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
897725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
897825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'u':
897925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
898025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
898125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'd':
898225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
898325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
898425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
898525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  case 'b':
898625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
898725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    GElf_Xword bit = 1;
898825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    const char *pfx = "<";
898925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
899025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
899125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (av->a_un.a_val & bit)
899225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
899325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    printf ("%s%s", pfx, p);
899425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    pfx = " ";
899525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
899625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		bit <<= 1;
899725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
899825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf (">\n");
899925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
900025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
900125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  default:
900225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    abort ();
900325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
900425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
900525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
900625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
900703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
900803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesbuf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
900903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
901003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return ptr < end && (size_t) (end - ptr) >= sz;
901103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
901203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
901303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
901403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesbuf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
901503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      int *retp)
901603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
901703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! buf_has_data (*ptrp, end, 4))
901803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return false;
901903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
902003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
902103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return true;
902203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
902303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
902403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
902503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesbuf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
902603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		uint64_t *retp)
902703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
902803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
902903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! buf_has_data (*ptrp, end, sz))
903003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return false;
903103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
903203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  union
903303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  {
903403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    uint64_t u64;
903503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    uint32_t u32;
903603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  } u;
903703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
903803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
903903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
904003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (sz == 4)
904103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    *retp = u.u32;
904203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  else
904303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    *retp = u.u64;
904403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return true;
904503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
904603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
904703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
904803333823c75a1c1887e923828113a1b0fd12020cElliott Hugheshandle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
904903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
905003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
905103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (data == NULL)
905203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0,
905303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
905403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
905503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  unsigned char const *ptr = data->d_buf;
905603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  unsigned char const *const end = data->d_buf + data->d_size;
905703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
905803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Siginfo head is three ints: signal number, error number, origin
905903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     code.  */
906003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int si_signo, si_errno, si_code;
906103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! buf_read_int (core, &ptr, end, &si_signo)
906203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      || ! buf_read_int (core, &ptr, end, &si_errno)
906303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      || ! buf_read_int (core, &ptr, end, &si_code))
906403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
906503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    fail:
906603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf ("    Not enough data in NT_SIGINFO note.\n");
906703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
906803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
906903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
907003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Next is a pointer-aligned union of structures.  On 64-bit
907103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     machines, that implies a word of padding.  */
907203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (gelf_getclass (core) == ELFCLASS64)
907303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    ptr += 4;
907403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
907503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  printf ("    si_signo: %d, si_errno: %d, si_code: %d\n",
907603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  si_signo, si_errno, si_code);
907703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
907803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (si_code > 0)
907903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    switch (si_signo)
908003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      {
908103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      case SIGILL:
908203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      case SIGFPE:
908303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      case SIGSEGV:
908403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      case SIGBUS:
908503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
908603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  uint64_t addr;
908703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (! buf_read_ulong (core, &ptr, end, &addr))
908803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto fail;
908903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  printf ("    fault address: %#" PRIx64 "\n", addr);
909003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  break;
909103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
909203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      default:
909303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	;
909403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      }
909503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  else if (si_code == SI_USER)
909603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
909703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      int pid, uid;
909803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (! buf_read_int (core, &ptr, end, &pid)
909903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  || ! buf_read_int (core, &ptr, end, &uid))
910003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto fail;
910103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf ("    sender PID: %d, sender UID: %d\n", pid, uid);
910203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
910303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
910403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
910503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
910603333823c75a1c1887e923828113a1b0fd12020cElliott Hugheshandle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
910703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
910803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
910903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (data == NULL)
911003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    error (EXIT_FAILURE, 0,
911103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
911203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
911303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  unsigned char const *ptr = data->d_buf;
911403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  unsigned char const *const end = data->d_buf + data->d_size;
911503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
911603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  uint64_t count, page_size;
911703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! buf_read_ulong (core, &ptr, end, &count)
911803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      || ! buf_read_ulong (core, &ptr, end, &page_size))
911903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
912003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    fail:
912103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf ("    Not enough data in NT_FILE note.\n");
912203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return;
912303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
912403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
912503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
912603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
912703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (count > maxcount)
912803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    goto fail;
912903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
913003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Where file names are stored.  */
913103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  unsigned char const *const fstart = ptr + 3 * count * addrsize;
913203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  char const *fptr = (char *) fstart;
913303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
913403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  printf ("    %" PRId64 " files:\n", count);
913503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (uint64_t i = 0; i < count; ++i)
913603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
913703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      uint64_t mstart, mend, moffset;
913803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (! buf_read_ulong (core, &ptr, fstart, &mstart)
913903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  || ! buf_read_ulong (core, &ptr, fstart, &mend)
914003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  || ! buf_read_ulong (core, &ptr, fstart, &moffset))
914103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto fail;
914203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
914303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
914403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (fnext == NULL)
914503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	goto fail;
914603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
914703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      int ct = printf ("      %08" PRIx64 "-%08" PRIx64
914803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		       " %08" PRIx64 " %" PRId64,
914903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		       mstart, mend, moffset * page_size, mend - mstart);
915003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
915103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
915203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      fptr = fnext + 1;
915303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
915403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
915503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
915625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
915725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
915825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  const char *name, const void *desc)
915925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
916025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Word regs_offset;
916125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nregloc;
916225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Register_Location *reglocs;
916325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t nitems;
916425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Ebl_Core_Item *items;
916525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
916625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! ebl_core_note (ebl, nhdr, name,
916725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
916825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
916925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
917025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Pass 0 for DESCSZ when there are registers in the note,
917125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     so that the ITEMS array does not describe the whole thing.
917225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     For non-register notes, the actual descsz might be a multiple
917325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     of the unit size, not just exactly the unit size.  */
917425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int colno = handle_core_items (ebl->elf, desc,
917525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  nregloc == 0 ? nhdr->n_descsz : 0,
917625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  items, nitems);
917725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (colno != 0)
917825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    putchar_unlocked ('\n');
917925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
918025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
918125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 reglocs, nregloc);
918225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (colno != 0)
918325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    putchar_unlocked ('\n');
918425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
918525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
918625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
918725b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
918825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   GElf_Off start, Elf_Data *data)
918925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
919025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
919125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
919225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
919325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto bad_note;
919425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
919525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t offset = 0;
919625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Nhdr nhdr;
919725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t name_offset;
919825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t desc_offset;
919925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (offset < data->d_size
920025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 && (offset = gelf_getnote (data, offset,
920125b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    &nhdr, &name_offset, &desc_offset)) > 0)
920225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
920325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *name = data->d_buf + name_offset;
920425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *desc = data->d_buf + desc_offset;
920525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
920625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[100];
920725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf2[100];
920825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
920925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      (int) nhdr.n_namesz, name, nhdr.n_descsz,
921025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr->e_type == ET_CORE
921125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
921225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 buf, sizeof (buf))
921325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      : ebl_object_note_type_name (ebl, name, nhdr.n_type,
921425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   buf2, sizeof (buf2)));
921525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
921625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Filter out invalid entries.  */
921725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (memchr (name, '\0', nhdr.n_namesz) != NULL
921825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* XXX For now help broken Linux kernels.  */
921925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || 1)
922025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
922125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ehdr->e_type == ET_CORE)
922225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
922325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (nhdr.n_type == NT_AUXV
922425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
922525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      || (nhdr.n_namesz == 5 && name[4] == '\0'))
922625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && !memcmp (name, "CORE", 4))
922725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
922825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				  start + desc_offset);
922903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
923003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		switch (nhdr.n_type)
923103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  {
923203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  case NT_SIGINFO:
923303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    handle_siginfo_note (ebl->elf, nhdr.n_descsz,
923403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					 start + desc_offset);
923503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    break;
923603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
923703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  case NT_FILE:
923803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    handle_file_note (ebl->elf, nhdr.n_descsz,
923903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				      start + desc_offset);
924003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    break;
924103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
924203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  default:
924303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    handle_core_note (ebl, &nhdr, name, desc);
924403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  }
924525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
924625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		handle_core_note (ebl, &nhdr, name, desc);
924725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
924825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
924925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
925025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
925125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
925225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
925325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (offset == data->d_size)
925425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
925525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
925625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bad_note:
925725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  error (EXIT_FAILURE, 0,
925825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 gettext ("cannot get content of note section: %s"),
925925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 elf_errmsg (-1));
926025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
926125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
926225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
926325b3c049e70834cf33790a28643ab058b507b35cBen Chenghandle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
926425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
926525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If we have section headers, just look for SHT_NOTE sections.
926625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     In a debuginfo file, the program headers are not reliable.  */
926725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shnum != 0)
926825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
926925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the section header string table index.  */
927025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t shstrndx;
927125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
927225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0,
927325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("cannot get section header string table index"));
927425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
927525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = NULL;
927625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
927725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
927825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr shdr_mem;
927925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
928025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
928125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
928225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Not what we are looking for.  */
928325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
928425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
928525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\
928625b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
928725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn),
928825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
928925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_size, shdr->sh_offset);
929025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
929125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
929225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     elf_getdata (scn, NULL));
929325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
929425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
929525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
929625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
929725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We have to look through the program header to find the note
929825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     sections.  There can be more than one.  */
929925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < phnum; ++cnt)
930025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
930125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr mem;
930225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
930325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
930425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (phdr == NULL || phdr->p_type != PT_NOTE)
930525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Not what we are looking for.  */
930625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
930725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
930825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("\
930925b3c049e70834cf33790a28643ab058b507b35cBen Cheng\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
931025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      phdr->p_filesz, phdr->p_offset);
931125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
931225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      handle_notes_data (ebl, ehdr, phdr->p_offset,
931325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 elf_getdata_rawchunk (ebl->elf,
931425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       phdr->p_offset, phdr->p_filesz,
931525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					       ELF_T_NHDR));
931625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
931725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
931825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
931925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
932025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
932125b3c049e70834cf33790a28643ab058b507b35cBen Chenghex_dump (const uint8_t *data, size_t len)
932225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
932325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t pos = 0;
932425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (pos < len)
932525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
932625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("  0x%08Zx ", pos);
932725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
932825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const size_t chunk = MIN (len - pos, 16);
932925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
933025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < chunk; ++i)
933125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (i % 4 == 3)
933225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%02x ", data[pos + i]);
933325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	else
933425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%02x", data[pos + i]);
933525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
933625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (chunk < 16)
933725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
933825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
933925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (size_t i = 0; i < chunk; ++i)
934025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
934125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unsigned char b = data[pos + i];
934225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf ("%c", isprint (b) ? b : '.');
934325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
934425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
934525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      putchar ('\n');
934625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      pos += chunk;
934725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
934825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
934925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
935025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
935125b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
935225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
935325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
935425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
935525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), name);
935625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
935725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
935825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
935925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (data == NULL)
936025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
936125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_ndxscn (scn), name, elf_errmsg (-1));
936225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
936325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
936425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
936525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   " bytes at offset %#0" PRIx64 ":\n"),
936625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn), name,
936725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_size, shdr->sh_offset);
936825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  hex_dump (data->d_buf, data->d_size);
936925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
937025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
937125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
937225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
937325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
937425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
937525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
937625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
937725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    printf (gettext ("\nSection [%Zu] '%s' has no strings to dump.\n"),
937825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_ndxscn (scn), name);
937925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
938025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
938125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
938225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (data == NULL)
938325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
938425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       elf_ndxscn (scn), name, elf_errmsg (-1));
938525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
938625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
938725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
938825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   " bytes at offset %#0" PRIx64 ":\n"),
938925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf_ndxscn (scn), name,
939025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  shdr->sh_size, shdr->sh_offset);
939125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
939225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *start = data->d_buf;
939325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *const limit = start + data->d_size;
939425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  do
939525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
939625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const char *end = memchr (start, '\0', limit - start);
939725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      const size_t pos = start - (const char *) data->d_buf;
939825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (end == NULL))
939925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
940025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf ("  [%6Zx]- %.*s\n",
940125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  pos, (int) (limit - start), start);
940225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  break;
940325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
940425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      printf ("  [%6Zx]  %s\n", pos, start);
940525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      start = end + 1;
940625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    } while (start < limit);
940725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
940825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
940925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
941025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
941125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
941225b3c049e70834cf33790a28643ab058b507b35cBen Chengfor_each_section_argument (Elf *elf, const struct section_argument *list,
941325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
941425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					 const char *name))
941525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
941625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
941725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
941825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
941925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
942025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
942125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
942225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (const struct section_argument *a = list; a != NULL; a = a->next)
942325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
942425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn;
942525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
942625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *name = NULL;
942725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
942825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *endp = NULL;
942925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned long int shndx = strtoul (a->arg, &endp, 0);
943025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp != a->arg && *endp == '\0')
943125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
943225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn = elf_getscn (elf, shndx);
943325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (scn == NULL)
943425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
943525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
943625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      continue;
943725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
943825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
943925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
944025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
944125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   elf_errmsg (-1));
944225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
944325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
944425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
944525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
944625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Need to look up the section by name.  */
944725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn = NULL;
944825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool found = false;
944925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while ((scn = elf_nextscn (elf, scn)) != NULL)
945025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
945125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
945225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
945325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
945425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (name == NULL)
945525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		continue;
945625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!strcmp (name, a->arg))
945725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
945825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  found = true;
945925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  (*dump) (scn, &shdr_mem, name);
946025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
946125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
946225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
946325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (!found) && !a->implicit)
946425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
946525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
946625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
946725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
946825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
946925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
947025b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_data (Ebl *ebl)
947125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
947225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
947325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
947425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
947525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
947625b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_strings (Ebl *ebl)
947725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
947825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for_each_section_argument (ebl->elf, string_sections, &print_string_section);
947925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
948025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
948125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
948225b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_strings (Ebl *ebl)
948325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
948425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Get the section header string table index.  */
948525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrndx;
948625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
948725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0,
948825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   gettext ("cannot get section header string table index"));
948925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
949025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn;
949125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr shdr_mem;
949225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *name;
949325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  scn = NULL;
949425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
949525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
949625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (gelf_getshdr (scn, &shdr_mem) == NULL)
949725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
949825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
949925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr_mem.sh_type != SHT_PROGBITS
950025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || !(shdr_mem.sh_flags & SHF_STRINGS))
950125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
950225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
950325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
950425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (name == NULL)
950525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
950625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
950725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_string_section (scn, &shdr_mem, name);
950825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
950925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
951025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
951125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
951225b3c049e70834cf33790a28643ab058b507b35cBen Chengdump_archive_index (Elf *elf, const char *fname)
951325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
951425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t narsym;
951525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
951625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (arsym == NULL)
951725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
951825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int result = elf_errno ();
951925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (result != ELF_E_NO_INDEX))
952025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0,
952125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("cannot get symbol index of archive '%s': %s"),
952225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       fname, elf_errmsg (result));
952325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
952425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
952525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
952625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
952725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
952825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
952925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  fname, narsym);
953025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
953125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t as_off = 0;
953225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
953325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
953425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (s->as_off != as_off)
953525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
953625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  as_off = s->as_off;
953725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
953825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf *subelf;
953925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (elf_rand (elf, as_off) == 0)
954025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
954125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   == NULL))
954225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
954325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while (1)
954425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
954525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (EXIT_FAILURE, 0,
954625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     gettext ("cannot extract member at offset %Zu in '%s': %s"),
954725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     as_off, fname, elf_errmsg (-1));
954825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
954925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const Elf_Arhdr *h = elf_getarhdr (subelf);
955025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
955125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
955225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
955325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_end (subelf);
955425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
955525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
955625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf ("\t%s\n", s->as_name);
955725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
955825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
955925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
956025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "debugpred.h"
9561