1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print information from ELF file in human-readable form.
2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   This file is part of Red Hat elfutils.
4441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
5441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   it under the terms of the GNU General Public License as published by the
8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Free Software Foundation; version 2 of the License.
9441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   General Public License for more details.
14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   You should have received a copy of the GNU General Public License along
16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is an included package of the Open Invention Network.
20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   An included package of the Open Invention Network is a package for which
21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Open Invention Network licensees cross-license their patents.  No patent
22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   license is granted, either expressly or impliedly, by designation as an
23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   included package.  Should you wish to participate in the Open Invention
24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Network licensing program, please visit www.openinventionnetwork.com
25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   <http://www.openinventionnetwork.com>.  */
26441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
27441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef HAVE_CONFIG_H
28441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# include <config.h>
29441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
30441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
31441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <argp.h>
32441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <assert.h>
33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <ctype.h>
34441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <dwarf.h>
35441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <errno.h>
36441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <error.h>
37441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <fcntl.h>
38441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <gelf.h>
39441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <inttypes.h>
40441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <langinfo.h>
41441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libdw.h>
42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libdwfl.h>
43441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libintl.h>
44441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <locale.h>
45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdarg.h>
46441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdbool.h>
47441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdlib.h>
48441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <string.h>
49441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <time.h>
50441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <unistd.h>
51441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/param.h>
52441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
53441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <system.h>
54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libelf/libelfP.h"
55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libelf/common.h"
56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libebl/libeblP.h"
57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include "../libdw/libdwP.h"
58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libdwfl/libdwflP.h"
59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include "../libdw/memory-access.h"
60441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
61441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
62441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name and version of program.  */
63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_version (FILE *stream, struct argp_state *state);
64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Bug report address.  */
67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconst char *argp_program_bug_address = PACKAGE_BUGREPORT;
68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Definitions of arguments for argp functions.  */
70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct argp_option options[] =
71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "all", 'a', NULL, 0, N_("Equivalent to: -h -l"), 0 },
74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
76441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "histogram", 'I', NULL, 0,
77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Display histogram of bucket list lengths"), 0 },
78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "section-headers", 'S', NULL, 0, N_("Display the sections' header"), 0 },
82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
85441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
86441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    N_("Display DWARF section content.  SECTION can be one of abbrev, "
87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng       "aranges, frame, info, loc, line, ranges, pubnames, str, or macinfo."),
88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    0 },
89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "notes", 'n', NULL, 0, N_("Display the core notes"), 0 },
90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  { "arch-specific", 'A', NULL, 0,
91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Display architecture specific information (if any)"), 0 },
92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "hex-dump", 'x', "SECTION", 0,
93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Print string contents of sections"), 0 },
96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { "archive-index", 'c', NULL, 0,
98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Display the symbol index of an archive"), 0 },
99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, N_("Output control:"), 0 },
101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, NULL, 0 }
103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Short description of program.  */
106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char doc[] = N_("\
107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectPrint information from ELF file in human-readable form.");
108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Strings for arguments in help texts.  */
110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char args_doc[] = N_("FILE...");
111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Prototype for option handler.  */
113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Data structure to communicate with argp functions.  */
116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic struct argp argp =
117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  options, parse_opt, args_doc, doc, NULL, NULL, NULL
119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Flags set by the option controlling the output.  */
123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if dynamic segment should be printed.  */
125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_dynamic_table;
126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if the file header should be printed.  */
128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_file_header;
129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if the program headers should be printed.  */
131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_program_header;
132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if relocations should be printed.  */
134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_relocations;
135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if the section headers should be printed.  */
137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_section_header;
138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if the symbol table should be printed.  */
140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_symbol_table;
141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if the version information should be printed.  */
143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_version_info;
144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if section groups should be printed.  */
146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_section_groups;
147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if bucket list length histogram should be printed.  */
149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_histogram;
150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if the architecture specific data should be printed.  */
152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_arch;
153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if note section content should be printed.  */
155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool print_notes;
156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* True if SHF_STRINGS section content should be printed.  */
158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool print_string_sections;
159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* True if archive index should be printed.  */
161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool print_archive_index;
162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* True if any of the control options except print_archive_index is set.  */
164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool any_control_option;
165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Select printing of debugging sections.  */
167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic enum section_e
168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_abbrev = 1,	/* .debug_abbrev  */
170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_aranges = 2,	/* .debug_aranges  */
171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_frame = 4,	/* .debug_frame or .eh_frame  */
172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_info = 8,	/* .debug_info  */
173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_line = 16,	/* .debug_line  */
174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_loc = 32,	/* .debug_loc  */
175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_pubnames = 64,/* .debug_pubnames  */
176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_str = 128,	/* .debug_str  */
177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_macinfo = 256,/* .debug_macinfo  */
178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  section_ranges = 512, /* .debug_ranges  */
179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  section_all = (section_abbrev | section_aranges | section_frame
180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 | section_info | section_line | section_loc
181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 | section_pubnames | section_str | section_macinfo
182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 | section_ranges)
183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} print_debug_sections;
184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Select hex dumping of sections.  */
186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct section_argument *dump_data_sections;
187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct section_argument **dump_data_sections_tail = &dump_data_sections;
188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Select string dumping of sections.  */
190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct section_argument *string_sections;
191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct section_argument **string_sections_tail = &string_sections;
192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct section_argument
194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct section_argument *next;
196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *arg;
197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng};
198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Number of sections in the file.  */
200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic size_t shnum;
201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Declarations of local functions.  */
204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void process_file (int fd, const char *fname, bool only_one);
205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void process_elf_file (Dwfl_Module *dwflmod, int fd);
206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_scngrp (Ebl *ebl);
210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr);
211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_relocs (Ebl *ebl);
212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_symtab (Ebl *ebl, int type);
215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_verinfo (Ebl *ebl);
217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void handle_versym (Ebl *ebl, Elf_Scn *scn,
220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   GElf_Shdr *shdr);
221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void handle_hash (Ebl *ebl);
223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_liblist (Ebl *ebl);
225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void dump_data (Ebl *ebl);
227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void dump_strings (Ebl *ebl);
228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_strings (Ebl *ebl);
229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void dump_archive_index (Elf *, const char *);
230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectint
233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmain (int argc, char *argv[])
234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Set locale.  */
236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  setlocale (LC_ALL, "");
237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Initialize the message catalog.  */
239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  textdomain (PACKAGE_TARNAME);
240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Parse and process arguments.  */
242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int remaining;
243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Before we start tell the ELF library which version we are using.  */
246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  elf_version (EV_CURRENT);
247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now process all the files given at the command line.  */
249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool only_one = remaining + 1 == argc;
250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  do
251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Open the file.  */
253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int fd = open (argv[remaining], O_RDONLY);
254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (fd == -1)
255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, errno, gettext ("cannot open input file"));
257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      process_file (fd, argv[remaining], only_one);
261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      close (fd);
263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (++remaining < argc);
265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return error_message_count != 0;
267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle program arguments.  */
271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t
272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengparse_opt (int key, char *arg,
273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   struct argp_state *state __attribute__ ((unused)))
274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (key)
276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'a':
278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_file_header = true;
279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_program_header = true;
280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_relocations = true;
281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_section_header = true;
282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_symbol_table = true;
283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_version_info = true;
284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_dynamic_table = true;
285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_section_groups = true;
286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_histogram = true;
287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_arch = true;
288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_notes = true;
289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'A':
292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_arch = true;
293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'd':
296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_dynamic_table = true;
297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'g':
300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_section_groups = true;
301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'h':
304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_file_header = true;
305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'I':
308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_histogram = true;
309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'l':
312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_program_header = true;
313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'n':
316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_notes = true;
317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'r':
320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_relocations = true;
321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     break;
323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'S':
324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_section_header = true;
325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 's':
328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_symbol_table = true;
329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'V':
332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      print_version_info = true;
333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      any_control_option = true;
334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'c':
336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      print_archive_index = true;
337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case 'w':
339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (arg == NULL)
340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections = section_all;
341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "abbrev") == 0)
342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_abbrev;
343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "aranges") == 0)
344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_aranges;
345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else if (strcmp (arg, "ranges") == 0)
346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	print_debug_sections |= section_ranges;
347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "frame") == 0)
348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_frame;
349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "info") == 0)
350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_info;
351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "loc") == 0)
352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_loc;
353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "line") == 0)
354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_line;
355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "pubnames") == 0)
356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_pubnames;
357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "str") == 0)
358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_str;
359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (strcmp (arg, "macinfo") == 0)
360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	print_debug_sections |= section_macinfo;
361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   arg);
365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  argp_help (&argp, stderr, ARGP_HELP_SEE,
366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     program_invocation_short_name);
367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  exit (1);
368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      any_control_option = true;
370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'p':
372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      any_control_option = true;
373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (arg == NULL)
374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  print_string_sections = true;
376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Fall through.  */
379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'x':
380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	struct section_argument *a = xmalloc (sizeof *a);
382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	a->arg = arg;
383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	a->next = NULL;
384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	struct section_argument ***tailp
385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	**tailp = a;
387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	*tailp = &a->next;
388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      any_control_option = true;
390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case ARGP_KEY_NO_ARGS:
392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      fputs (gettext ("Missing file name.\n"), stderr);
393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      goto do_argp_help;
394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case ARGP_KEY_FINI:
395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (! any_control_option && ! print_archive_index)
396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  fputs (gettext ("No operation specified.\n"), stderr);
398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	do_argp_help:
399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     program_invocation_short_name);
401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  exit (1);
402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return ARGP_ERR_UNKNOWN;
406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return 0;
408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the version information.  */
412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("\
417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectCopyright (C) %s Red Hat, Inc.\n\
418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectThis is free software; see the source for copying conditions.  There is NO\n\
419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng"), "2008");
421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Check if the file is an archive, and if so dump its index.  */
426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_archive_index (int fd, const char *fname, bool only_one)
428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Create an `Elf' descriptor.  */
430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (elf == NULL)
432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   elf_errmsg (-1));
434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (elf_kind (elf) == ELF_K_AR)
437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (!only_one)
439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("\n%s:\n\n", fname);
440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  dump_archive_index (elf, fname);
441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (0, 0,
444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       gettext ("'%s' is not an archive, cannot print archive index"),
445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       fname);
446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Now we can close the descriptor.  */
448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (elf_end (elf) != 0)
449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (0, 0, gettext ("error while closing Elf descriptor: %s"),
450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       elf_errmsg (-1));
451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Trivial callback used for checking if we opened an archive.  */
455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcount_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       void **userdata __attribute__ ((unused)),
458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       const char *name __attribute__ ((unused)),
459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       Dwarf_Addr base __attribute__ ((unused)),
460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       void *arg)
461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*(bool *) arg)
463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return DWARF_CB_ABORT;
464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *(bool *) arg = true;
465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return DWARF_CB_OK;
466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct process_dwflmod_args
469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int fd;
471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool only_one;
472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng};
473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprocess_dwflmod (Dwfl_Module *dwflmod,
476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 void **userdata __attribute__ ((unused)),
477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 const char *name __attribute__ ((unused)),
478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 Dwarf_Addr base __attribute__ ((unused)),
479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 void *arg)
480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const struct process_dwflmod_args *a = arg;
482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Print the file name.  */
484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (!a->only_one)
485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *fname;
487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf ("\n%s:\n\n", fname);
490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  process_elf_file (dwflmod, a->fd);
493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return DWARF_CB_OK;
495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Stub libdwfl callback, only the ELF handle already open is ever used.  */
498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengfind_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   void **userdata __attribute__ ((unused)),
501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   const char *modname __attribute__ ((unused)),
502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   Dwarf_Addr base __attribute__ ((unused)),
503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   const char *file_name __attribute__ ((unused)),
504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   const char *debuglink_file __attribute__ ((unused)),
505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   GElf_Word debuglink_crc __attribute__ ((unused)),
506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   char **debuginfo_file_name __attribute__ ((unused)))
507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return -1;
509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Process one input file.  */
512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprocess_file (int fd, const char *fname, bool only_one)
514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (print_archive_index)
516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    check_archive_index (fd, fname, only_one);
517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (!any_control_option)
519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return;
520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Duplicate an fd for dwfl_report_offline to swallow.  */
522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int dwfl_fd = dup (fd);
523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (dwfl_fd < 0))
524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, errno, "dup");
525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Use libdwfl in a trivial way to open the libdw handle for us.
527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     This takes care of applying relocations to DWARF data in ET_REL files.  */
528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const Dwfl_Callbacks callbacks =
529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .section_address = dwfl_offline_section_address,
531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .find_debuginfo = find_no_debuginfo
532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Dwfl *dwfl = dwfl_begin (&callbacks);
534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (dwfl != NULL))
535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    /* Let 0 be the logical address of the file (or first in archive).  */
536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    dwfl->offline_next_address = 0;
537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      struct stat64 st;
540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (fstat64 (fd, &st) != 0)
541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (0, errno, gettext ("cannot stat input file"));
542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else if (unlikely (st.st_size == 0))
543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (0, 0, gettext ("input file is empty"));
544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (0, 0, gettext ("failed reading '%s': %s"),
546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       fname, dwfl_errmsg (-1));
547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      dwfl_report_end (dwfl, NULL, NULL);
551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (only_one)
553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  bool seen = false;
556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Process the one or more modules gleaned from this file.  */
560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  dwfl_end (dwfl);
564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Process one ELF file.  */
568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprocess_elf_file (Dwfl_Module *dwflmod, int fd)
570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Addr dwflbias;
572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr ehdr_mem;
575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr == NULL)
578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    elf_error:
580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Ebl *ebl = ebl_openbackend (elf);
585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (ebl == NULL))
586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    ebl_error:
588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, errno, gettext ("cannot create EBL handle"));
589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Determine the number of sections.  */
593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshnum (ebl->elf, &shnum) < 0))
594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot determine number of sections: %s"),
596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   elf_errmsg (-1));
597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     and may have applied relocation to some sections.
600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     So we need to get a fresh Elf handle on the file to display those.  */
601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool print_unrelocated = (print_section_header
602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    || print_relocations
603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    || dump_data_sections != NULL
604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    || print_notes);
605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *pure_elf = NULL;
607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Ebl *pure_ebl = ebl;
608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (ehdr->e_type == ET_REL && print_unrelocated)
609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Read the file afresh.  */
611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      off64_t aroff = elf_getaroff (elf);
612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (aroff > 0)
614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Archive member.  */
616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  (void) elf_rand (pure_elf, aroff);
617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  elf_end (pure_elf);
619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  pure_elf = armem;
620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (pure_elf == NULL)
622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto elf_error;
623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      pure_ebl = ebl_openbackend (pure_elf);
624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (pure_ebl == NULL)
625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto ebl_error;
626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_file_header)
629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    print_ehdr (ebl, ehdr);
630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_section_header)
631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_shdr (pure_ebl, ehdr);
632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_program_header)
633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    print_phdr (ebl, ehdr);
634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_section_groups)
635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_scngrp (ebl);
636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_dynamic_table)
637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    print_dynamic (ebl, ehdr);
638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_relocations)
639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_relocs (pure_ebl);
640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_histogram)
641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    handle_hash (ebl);
642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_symbol_table)
643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_symtab (ebl, SHT_DYNSYM);
644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_version_info)
645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_verinfo (ebl);
646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_symbol_table)
647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_symtab (ebl, SHT_SYMTAB);
648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (print_arch)
649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_liblist (ebl);
650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_arch)
651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_attributes (ebl, ehdr);
652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (dump_data_sections != NULL)
653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    dump_data (pure_ebl);
654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (string_sections != NULL)
655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    dump_strings (ebl);
656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_debug_sections != 0)
657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_debug (dwflmod, ebl, ehdr);
658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (print_notes)
659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    handle_notes (pure_ebl, ehdr);
660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (print_string_sections)
661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    print_strings (ebl);
662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  ebl_closebackend (ebl);
664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (pure_ebl != ebl)
666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ebl_closebackend (pure_ebl);
668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      elf_end (pure_elf);
669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print file type.  */
674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_file_type (unsigned short int e_type)
676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (e_type <= ET_CORE))
678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      static const char *const knowntypes[] =
680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	N_("NONE (None)"),
682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	N_("REL (Relocatable file)"),
683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	N_("EXEC (Executable file)"),
684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	N_("DYN (Shared object file)"),
685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	N_("CORE (Core file)")
686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      };
687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      puts (gettext (knowntypes[e_type]));
688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (gettext ("OS Specific: (%x)\n"),  e_type);
691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (gettext ("Processor Specific: (%x)\n"),  e_type);
693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    puts ("???");
695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print ELF header.  */
699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputs_unlocked (gettext ("ELF Header:\n  Magic:  "), stdout);
703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (" %02hhx", ehdr->e_ident[cnt]);
705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\n  Class:                             %s\n"),
707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  : "\?\?\?");
710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Data:                              %s\n"),
712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ? "2's complement, little endian"
714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ? "2's complement, big endian" : "\?\?\?");
716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  printf (gettext ("  Ident Version:                     %hhd %s\n"),
718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_ident[EI_VERSION],
719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  : "(\?\?\?)");
721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char buf[512];
723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  OS/ABI:                            %s\n"),
724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  ABI Version:                       %hhd\n"),
727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_ident[EI_ABIVERSION]);
728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputs_unlocked (gettext ("  Type:                              "), stdout);
730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  print_file_type (ehdr->e_type);
731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Machine:                           %s\n"), ebl->name);
733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Version:                           %d %s\n"),
735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_version,
736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_entry);
740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_phoff, gettext ("(bytes into file)"));
743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Start of section headers:          %" PRId64 " %s\n"),
745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_shoff, gettext ("(bytes into file)"));
746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Flags:                             %s\n"),
748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Size of this header:               %" PRId16 " %s\n"),
751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_ehsize, gettext ("(bytes)"));
752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Size of program header entries:    %" PRId16 " %s\n"),
754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_phentsize, gettext ("(bytes)"));
755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Number of program headers entries: %" PRId16 "\n"),
757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_phnum);
758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Size of section header entries:    %" PRId16 " %s\n"),
760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_shentsize, gettext ("(bytes)"));
761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("  Number of section headers entries: %" PRId16),
763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ehdr->e_shnum);
764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_shnum == 0)
765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr != NULL)
769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		(uint32_t) shdr->sh_size);
771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	fputs_unlocked (gettext (" ([0] not available)"), stdout);
773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputc_unlocked ('\n', stdout);
775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr != NULL)
781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* We managed to get the zeroth section.  */
782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  (uint32_t) shdr->sh_link);
784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  buf[sizeof (buf) - 1] = '\0';
788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("  Section header string table index: XINDEX%s\n\n"),
791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      buf);
792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (gettext ("  Section header string table index: %" PRId16 "\n\n"),
795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ehdr->e_shstrndx);
796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *
800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectget_visibility_type (int value)
801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (value)
803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case STV_DEFAULT:
805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return "DEFAULT";
806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case STV_INTERNAL:
807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return "INTERNAL";
808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case STV_HIDDEN:
809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return "HIDDEN";
810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case STV_PROTECTED:
811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return "PROTECTED";
812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return "???";
814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the section headers.  */
819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shstrndx;
824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (! print_file_header)
826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (gettext ("\
827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectThere are %d section headers, starting at offset %#" PRIx64 ":\n\
828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\n"),
829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    ehdr->e_shnum, ehdr->e_shoff);
830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
833441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
835441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
836441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  puts (gettext ("Section Headers:"));
837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    puts (gettext ("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    puts (gettext ("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < shnum; ++cnt)
844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
845441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (scn == NULL))
848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get the section header.  */
852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr shdr_mem;
853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (shdr == NULL))
855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char flagbuf[20];
859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *cp = flagbuf;
860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_WRITE)
861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'W';
862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_ALLOC)
863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'A';
864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_EXECINSTR)
865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'X';
866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_MERGE)
867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'M';
868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_STRINGS)
869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'S';
870441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_INFO_LINK)
871441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'I';
872441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_LINK_ORDER)
873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'L';
874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_OS_NONCONFORMING)
875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'N';
876441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_GROUP)
877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'G';
878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_TLS)
879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'T';
880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_ORDERED)
881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'O';
882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr->sh_flags & SHF_EXCLUDE)
883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	*cp++ = 'E';
884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      *cp = '\0';
885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char buf[128];
887441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      " %2" PRId64 "\n",
890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      cnt,
891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ?: "<corrupt>",
893441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
895441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
896441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
897441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr->sh_addralign);
899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputc_unlocked ('\n', stdout);
902441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
903441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
904441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
905441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the program header.  */
906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_phnum == 0)
910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* No program header, this is OK in relocatable objects.  */
911441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
912441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  puts (gettext ("Program Headers:"));
914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    puts (gettext ("\
916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    puts (gettext ("\
919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Process all program headers.  */
922441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool has_relro = false;
923441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Addr relro_from = 0;
924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Addr relro_to = 0;
925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      char buf[128];
928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Phdr mem;
929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* If for some reason the header cannot be returned show this.  */
932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (phdr == NULL))
933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
934441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  puts ("  ???");
935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  continue;
936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
939441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
941441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_offset,
942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
944441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_filesz,
945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_memsz,
946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_flags & PF_R ? 'R' : ' ',
947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_flags & PF_W ? 'W' : ' ',
948441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_flags & PF_X ? 'E' : ' ',
949441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_align);
950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
951441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (phdr->p_type == PT_INTERP)
952441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
953441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* We can show the user the name of the interpreter.  */
954441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  size_t maxsize;
955441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
956441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (filedata != NULL && phdr->p_offset < maxsize)
958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf (gettext ("\t[Requesting program interpreter: %s]\n"),
959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    filedata + phdr->p_offset);
960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
961441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (phdr->p_type == PT_GNU_RELRO)
962441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
963441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  has_relro = true;
964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  relro_from = phdr->p_vaddr;
965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  relro_to = relro_from + phdr->p_memsz;
966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
972441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
973441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
974441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
975441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  puts (gettext ("\n Section to Segment mapping:\n  Segment Sections..."));
976441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
978441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
979441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Print the segment number.  */
980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("   %2.2zu     ", cnt);
981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Phdr phdr_mem;
983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
984441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* This must not happen.  */
985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (phdr == NULL))
986441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
987441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	       elf_errmsg (-1));
988441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Iterate over the sections.  */
990441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      bool in_relro = false;
991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bool in_ro = false;
992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (size_t inner = 1; inner < shnum; ++inner)
993441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
994441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* This should not happen.  */
996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (scn == NULL))
997441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
998441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   elf_errmsg (-1));
999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1000441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Get the section header.  */
1001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr shdr_mem;
1002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (shdr == NULL))
1004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    error (EXIT_FAILURE, 0,
1005441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   gettext ("cannot get section header: %s"),
1006441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   elf_errmsg (-1));
1007441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1008441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr->sh_size > 0
1009441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Compare allocated sections by VMA, unallocated
1010441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 sections by file offset.  */
1011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && (shdr->sh_flags & SHF_ALLOC
1012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  ? (shdr->sh_addr >= phdr->p_vaddr
1013441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     && (shdr->sh_addr + shdr->sh_size
1014441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 <= phdr->p_vaddr + phdr->p_memsz))
1015441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  : (shdr->sh_offset >= phdr->p_offset
1016441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     && (shdr->sh_offset + shdr->sh_size
1017441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 <= phdr->p_offset + phdr->p_filesz))))
1018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1019441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (has_relro && !in_relro
1020441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && shdr->sh_addr >= relro_from
1021441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  && shdr->sh_addr + shdr->sh_size <= relro_to)
1022441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  fputs_unlocked (" [RELRO:", stdout);
1024441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  in_relro = true;
1025441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  fputs_unlocked ("]", stdout);
1029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  in_relro =  false;
1030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else if (has_relro && in_relro
1032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       && shdr->sh_addr + shdr->sh_size > relro_to)
1033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		fputs_unlocked ("] <RELRO:", stdout);
1034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (!in_ro)
1037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
1038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      fputs_unlocked (" [RO:", stdout);
1039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      in_ro = true;
1040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
1041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
1043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  /* Determine the segment this section is part of.  */
1045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  size_t cnt2;
1046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Phdr *phdr2 = NULL;
1047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  for (cnt2 = 0; cnt2 < ehdr->e_phnum; ++cnt2)
1048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
1049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      GElf_Phdr phdr2_mem;
1050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  && shdr->sh_addr >= phdr2->p_vaddr
1054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  && (shdr->sh_addr + shdr->sh_size
1055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      <= phdr2->p_vaddr + phdr2->p_memsz))
1056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			break;
1057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
1058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (cnt2 < ehdr->e_phnum)
1060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
1061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			{
1063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  fputs_unlocked (" [RO:", stdout);
1064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  in_ro = true;
1065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			}
1066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			{
1068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  fputs_unlocked ("]", stdout);
1069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  in_ro = false;
1070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			}
1071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
1072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      printf (" %s",
1075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Signal that this sectin is only partially covered.  */
1078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (has_relro && in_relro
1079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       && shdr->sh_addr + shdr->sh_size > relro_to)
1080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  fputs_unlocked (">", stdout);
1082441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  in_relro =  false;
1083441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (in_relro || in_ro)
1087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	fputs_unlocked ("]", stdout);
1088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Finish the line.  */
1090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      fputc_unlocked ('\n', stdout);
1091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1092441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1093441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1095441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1097441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
1099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
1100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr symshdr_mem;
1103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
1105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      || symdata == NULL)
1108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
1111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
1112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
1115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Sym sym_mem;
1119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf ((grpref[0] & GRP_COMDAT)
1120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ? ngettext ("\
1121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      "\
1123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      data->d_size / sizeof (Elf32_Word) - 1)
1125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  : ngettext ("\
1126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      data->d_size / sizeof (Elf32_Word) - 1),
1129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_ndxscn (scn),
1130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, symshdr->sh_link,
1132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
1133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ?: gettext ("<INVALID SYMBOL>"),
1134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data->d_size / sizeof (Elf32_Word) - 1);
1135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr grpshdr_mem;
1139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 &grpshdr_mem);
1141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *str;
1143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf ("  [%2u] %s\n",
1144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      grpref[cnt],
1145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      grpshdr != NULL
1146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ? str : gettext ("<INVALID SECTION>"));
1148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_scngrp (Ebl *ebl)
1154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Find all relocation sections and handle them.  */
1156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn = NULL;
1157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       /* Handle the section if it is a symbol table.  */
1161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
1162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	handle_scngrp (ebl, scn, shdr);
1166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct flags
1171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int mask;
1173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const char *str;
1174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} dt_flags[] =
1175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
1176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_ORIGIN, "ORIGIN" },
1177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_SYMBOLIC, "SYMBOLIC" },
1178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_TEXTREL, "TEXTREL" },
1179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_BIND_NOW, "BIND_NOW" },
1180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_STATIC_TLS, "STATIC_TLS" }
1181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  };
1182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct flags dt_flags_1[] =
1185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
1186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_NOW, "NOW" },
1187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_GLOBAL, "GLOBAL" },
1188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_GROUP, "GROUP" },
1189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_NODELETE, "NODELETE" },
1190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_LOADFLTR, "LOADFLTR" },
1191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_INITFIRST, "INITFIRST" },
1192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_NOOPEN, "NOOPEN" },
1193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_ORIGIN, "ORIGIN" },
1194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_DIRECT, "DIRECT" },
1195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_TRANS, "TRANS" },
1196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_INTERPOSE, "INTERPOSE" },
1197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_NODEFLIB, "NODEFLIB" },
1198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_NODUMP, "NODUMP" },
1199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_CONFALT, "CONFALT" },
1200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_ENDFILTEE, "ENDFILTEE" },
1201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_DISPRELDNE, "DISPRELDNE" },
1202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_1_DISPRELPND, "DISPRELPND" },
1203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  };
1204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct flags dt_feature_1[] =
1207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
1208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DTF_1_PARINIT, "PARINIT" },
1209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DTF_1_CONFEXP, "CONFEXP" }
1210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  };
1211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const int ndt_feature_1 = (sizeof (dt_feature_1)
1212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				  / sizeof (dt_feature_1[0]));
1213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct flags dt_posflag_1[] =
1215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
1216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_P1_LAZYLOAD, "LAZYLOAD" },
1217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    { DF_P1_GROUPPERM, "GROUPPERM" }
1218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  };
1219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				  / sizeof (dt_posflag_1[0]));
1221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_flags (int class, GElf_Xword d_val, const struct flags *flags,
1225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		int nflags)
1226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  bool first = true;
1228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int cnt;
1229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < nflags; ++cnt)
1231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    if (d_val & flags[cnt].mask)
1232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
1233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (!first)
1234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  putchar_unlocked (' ');
1235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	fputs_unlocked (flags[cnt].str, stdout);
1236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	d_val &= ~flags[cnt].mask;
1237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	first = false;
1238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
1239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (d_val != 0)
1241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (!first)
1243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	putchar_unlocked (' ');
1244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  putchar_unlocked ('\n');
1248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_dt_flags (int class, GElf_Xword d_val)
1253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  print_flags (class, d_val, dt_flags, ndt_flags);
1255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_dt_flags_1 (int class, GElf_Xword d_val)
1260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_dt_feature_1 (int class, GElf_Xword d_val)
1267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_dt_posflag_1 (int class, GElf_Xword d_val)
1274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int class = gelf_getclass (ebl->elf);
1283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr glink;
1284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data;
1285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
1286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shstrndx;
1287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
1289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  data = elf_getdata (scn, NULL);
1290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
1294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
1297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext ("\
1299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
1301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr->sh_size / shdr->sh_entsize),
1303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
1304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr->sh_offset,
1306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (int) shdr->sh_link,
1307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx,
1308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    &glink)->sh_name));
1310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputs_unlocked (gettext ("  Type              Value\n"), stdout);
1311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
1313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Dyn dynmem;
1315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dyn == NULL)
1317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
1318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char buf[64];
1320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("  %-17s ",
1321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      switch (dyn->d_tag)
1324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_NULL:
1326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_DEBUG:
1327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_BIND_NOW:
1328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_TEXTREL:
1329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* No further output.  */
1330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  fputc_unlocked ('\n', stdout);
1331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_NEEDED:
1334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext ("Shared library: [%s]\n"),
1335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_SONAME:
1339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext ("Library soname: [%s]\n"),
1340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RPATH:
1344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext ("Library rpath: [%s]\n"),
1345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RUNPATH:
1349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext ("Library runpath: [%s]\n"),
1350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
1351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_PLTRELSZ:
1354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RELASZ:
1355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_STRSZ:
1356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RELSZ:
1357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RELAENT:
1358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_SYMENT:
1359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RELENT:
1360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_PLTPADSZ:
1361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_MOVEENT:
1362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_MOVESZ:
1363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_INIT_ARRAYSZ:
1364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_FINI_ARRAYSZ:
1365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_SYMINSZ:
1366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_SYMINENT:
1367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_GNU_CONFLICTSZ:
1368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_GNU_LIBLISTSZ:
1369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_VERDEFNUM:
1373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_VERNEEDNUM:
1374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RELACOUNT:
1375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_RELCOUNT:
1376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
1377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_PLTREL:
1380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0));
1381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_FLAGS:
1384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  print_dt_flags (class, dyn->d_un.d_val);
1385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_FLAGS_1:
1388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  print_dt_flags_1 (class, dyn->d_un.d_val);
1389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_FEATURE_1:
1392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  print_dt_feature_1 (class, dyn->d_un.d_val);
1393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DT_POSFLAG_1:
1396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  print_dt_posflag_1 (class, dyn->d_un.d_val);
1397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	default:
1400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf ("%#0*" PRIx64 "\n",
1401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
1402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the dynamic segment.  */
1409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprint_dynamic (Ebl *ebl, GElf_Ehdr *ehdr)
1411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int i = 0; i < ehdr->e_phnum; ++i)
1413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Phdr phdr_mem;
1415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
1416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
1418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr shdr_mem;
1421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
1423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    handle_dynamic (ebl, scn, shdr);
1424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
1425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print relocations.  */
1431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_relocs (Ebl *ebl)
1433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Find all relocation sections and handle them.  */
1435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn = NULL;
1436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       /* Handle the section if it is a symbol table.  */
1440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
1441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (shdr != NULL))
1444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr->sh_type == SHT_REL)
1446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    handle_relocs_rel (ebl, scn, shdr);
1447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (shdr->sh_type == SHT_RELA)
1448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    handle_relocs_rela (ebl, scn, shdr);
1449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle a relocation section.  */
1455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int class = gelf_getclass (ebl->elf);
1459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int nentries = shdr->sh_size / shdr->sh_entsize;
1460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
1462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
1463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the symbol table information.  */
1467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr symshdr_mem;
1469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *symdata = elf_getdata (symscn, NULL);
1471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header of the section the relocations are for.  */
1473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr destshdr_mem;
1474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      &destshdr_mem);
1476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr->sh_offset);
1481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Search for the optional extended section index table.  */
1485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *xndxdata = NULL;
1486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int xndxscnidx = elf_scnshndx (scn);
1487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (xndxscnidx > 0))
1488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
1491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
1492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
1495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_info != 0)
1497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (ngettext ("\
1498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
1500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      nentries),
1502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    (unsigned int) elf_ndxscn (scn),
1503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    (unsigned int) shdr->sh_info,
1505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr->sh_offset,
1507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    nentries);
1508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
1509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* The .rel.dyn section does not refer to a specific section but
1510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       instead of section index zero.  Do not try to print a section
1511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       name.  */
1512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    printf (ngettext ("\
1513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
1515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      nentries),
1517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    (unsigned int) elf_ndxscn (scn),
1518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    shdr->sh_offset,
1520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    nentries);
1521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputs_unlocked (class == ELFCLASS32
1522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  ? gettext ("\
1523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Offset      Type                 Value       Name\n")
1524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  : gettext ("\
1525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Offset              Type                 Value               Name\n"),
1526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 stdout);
1527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int cnt = 0; cnt < nentries; ++cnt)
1529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Rel relmem;
1531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
1532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (rel != NULL))
1533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  char buf[128];
1535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym symmem;
1536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf32_Word xndx;
1537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					    GELF_R_SYM (rel->r_info),
1539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					    &symmem, &xndx);
1540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (sym == NULL))
1541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* Avoid the leading R_ which isn't carrying any
1545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information.  */
1546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					   buf, sizeof (buf)) + 2
1548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    : gettext ("<INVALID RELOC>"),
1549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    gettext ("INVALID SYMBOL"),
1550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    (long int) GELF_R_SYM (rel->r_info));
1551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    likely (ebl_reloc_type_check (ebl,
1555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						  GELF_R_TYPE (rel->r_info)))
1556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* Avoid the leading R_ which isn't carrying any
1557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information.  */
1558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					   buf, sizeof (buf)) + 2
1560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    : gettext ("<INVALID RELOC>"),
1561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
1562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
1564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   sym->st_shndx == SHN_XINDEX
1567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   ? xndx : sym->st_shndx),
1568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       &destshdr_mem);
1569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (destshdr == NULL))
1571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
1572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* Avoid the leading R_ which isn't carrying any
1575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   information.  */
1576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       buf, sizeof (buf)) + 2
1578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			: gettext ("<INVALID RELOC>"),
1579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			gettext ("INVALID SECTION"),
1580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			(long int) (sym->st_shndx == SHN_XINDEX
1581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    ? xndx : sym->st_shndx));
1582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
1583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
1584441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* Avoid the leading R_ which isn't carrying any
1587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   information.  */
1588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       buf, sizeof (buf)) + 2
1590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			: gettext ("<INVALID RELOC>"),
1591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			class == ELFCLASS32 ? 10 : 18, sym->st_value,
1592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1598441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle a relocation section.  */
1600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int class = gelf_getclass (ebl->elf);
1604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int nentries = shdr->sh_size / shdr->sh_entsize;
1605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
1607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data = elf_getdata (scn, NULL);
1608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1610441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the symbol table information.  */
1612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr symshdr_mem;
1614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *symdata = elf_getdata (symscn, NULL);
1616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header of the section the relocations are for.  */
1618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr destshdr_mem;
1619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
1620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				      &destshdr_mem);
1621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
1623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
1625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      shdr->sh_offset);
1626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
1627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Search for the optional extended section index table.  */
1630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *xndxdata = NULL;
1631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int xndxscnidx = elf_scnshndx (scn);
1632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (xndxscnidx > 0))
1633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
1634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
1636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shstrndx;
1637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
1640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext ("\
1642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
1643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
1644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
1645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    nentries),
1646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_ndxscn (scn),
1647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) shdr->sh_info,
1649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
1650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr->sh_offset,
1651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  nentries);
1652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputs_unlocked (class == ELFCLASS32
1653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  ? gettext ("\
1654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Offset      Type            Value       Addend Name\n")
1655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  : gettext ("\
1656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Offset              Type            Value               Addend Name\n"),
1657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  stdout);
1658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (int cnt = 0; cnt < nentries; ++cnt)
1660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Rela relmem;
1662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
1663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (rel != NULL))
1664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  char buf[64];
1666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Sym symmem;
1667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf32_Word xndx;
1668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					    GELF_R_SYM (rel->r_info),
1670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					    &symmem, &xndx);
1671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (sym == NULL))
1673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* Avoid the leading R_ which isn't carrying any
1677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information.  */
1678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					   buf, sizeof (buf)) + 2
1680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    : gettext ("<INVALID RELOC>"),
1681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    gettext ("INVALID SYMBOL"),
1682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    (long int) GELF_R_SYM (rel->r_info));
1683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
1684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf ("\
1685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
1686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    likely (ebl_reloc_type_check (ebl,
1688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						  GELF_R_TYPE (rel->r_info)))
1689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    /* Avoid the leading R_ which isn't carrying any
1690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       information.  */
1691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					   buf, sizeof (buf)) + 2
1693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    : gettext ("<INVALID RELOC>"),
1694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
1695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    rel->r_addend,
1696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
1697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
1698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
1700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   sym->st_shndx == SHN_XINDEX
1701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   ? xndx : sym->st_shndx),
1702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       &destshdr_mem);
1703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (shdr == NULL))
1705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
1706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* Avoid the leading R_ which isn't carrying any
1709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   information.  */
1710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       buf, sizeof (buf)) + 2
1712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			: gettext ("<INVALID RELOC>"),
1713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			gettext ("INVALID SECTION"),
1714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			(long int) (sym->st_shndx == SHN_XINDEX
1715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    ? xndx : sym->st_shndx));
1716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      else
1717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		printf ("\
1718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
1719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
1720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
1721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* Avoid the leading R_ which isn't carrying any
1722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   information.  */
1723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
1724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					       buf, sizeof (buf)) + 2
1725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			: gettext ("<INVALID RELOC>"),
1726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			class == ELFCLASS32 ? 10 : 18, sym->st_value,
1727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			rel->r_addend,
1728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
1729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the program header.  */
1736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_symtab (Ebl *ebl, int type)
1738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Find the symbol table(s).  For this we have to search through the
1740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     section table.  */
1741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn = NULL;
1742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Handle the section if it is a symbol table.  */
1746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
1747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
1750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	handle_symtab (ebl, scn, shdr);
1751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *versym_data = NULL;
1759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *verneed_data = NULL;
1760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *verdef_data = NULL;
1761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *xndx_data = NULL;
1762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int class = gelf_getclass (ebl->elf);
1763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf32_Word verneed_stridx = 0;
1764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf32_Word verdef_stridx = 0;
1765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
1767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
1768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
1769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
1770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Find out whether we have other sections we might need.  */
1772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *runscn = NULL;
1773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
1774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr runshdr_mem;
1776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
1777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (runshdr != NULL))
1779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (runshdr->sh_type == SHT_GNU_versym
1781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && runshdr->sh_link == elf_ndxscn (scn))
1782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Bingo, found the version information.  Now get the data.  */
1783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    versym_data = elf_getdata (runscn, NULL);
1784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (runshdr->sh_type == SHT_GNU_verneed)
1785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* This is the information about the needed versions.  */
1787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      verneed_data = elf_getdata (runscn, NULL);
1788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      verneed_stridx = runshdr->sh_link;
1789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (runshdr->sh_type == SHT_GNU_verdef)
1791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* This is the information about the defined versions.  */
1793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      verdef_data = elf_getdata (runscn, NULL);
1794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      verdef_stridx = runshdr->sh_link;
1795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
1797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && runshdr->sh_link == elf_ndxscn (scn))
1798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    /* Extended section index.  */
1799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    xndx_data = elf_getdata (runscn, NULL);
1800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
1804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
1805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
1806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
1807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
1808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now we can compute the number of entries in the section.  */
1810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int nsyms = data->d_size / (class == ELFCLASS32
1811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       ? sizeof (Elf32_Sym)
1812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       : sizeof (Elf64_Sym));
1813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
1815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
1816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    nsyms),
1817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) elf_ndxscn (scn),
1818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
1819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr glink;
1820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
1821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    " %lu local symbols  String table: [%2u] '%s'\n",
1822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr->sh_info),
1823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned long int) shdr->sh_info,
1824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) shdr->sh_link,
1825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx,
1826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
1827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    &glink)->sh_name));
1828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  fputs_unlocked (class == ELFCLASS32
1830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  ? gettext ("\
1831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
1832441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  : gettext ("\
1833441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
1834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  stdout);
1835441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
1837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      char typebuf[64];
1839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      char bindbuf[64];
1840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      char scnbuf[64];
1841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Elf32_Word xndx;
1842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Sym sym_mem;
1843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
1844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (sym == NULL))
1846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	continue;
1847441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Determine the real section index.  */
1849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (sym->st_shndx != SHN_XINDEX))
1850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	xndx = sym->st_shndx;
1851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("\
1853441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
1854441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      cnt,
1855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      class == ELFCLASS32 ? 8 : 16,
1856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      sym->st_value,
1857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      sym->st_size,
1858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
1859441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    typebuf, sizeof (typebuf)),
1860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
1861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       bindbuf, sizeof (bindbuf)),
1862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
1863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
1864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				sizeof (scnbuf), NULL, shnum),
1865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
1866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (versym_data != NULL)
1868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
1869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Get the version information.  */
1870441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Versym versym_mem;
1871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
1872441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
1874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
1875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      bool is_nobits = false;
1876441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      bool check_def = xndx != SHN_UNDEF;
1877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
1879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr symshdr_mem;
1881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Shdr *symshdr =
1882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
1883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  is_nobits = (symshdr != NULL
1885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			       && symshdr->sh_type == SHT_NOBITS);
1886441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1887441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (is_nobits || ! check_def)
1889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* We must test both.  */
1891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Vernaux vernaux_mem;
1892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Vernaux *vernaux = NULL;
1893441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t vn_offset = 0;
1894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Verneed verneed_mem;
1896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0,
1897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng							   &verneed_mem);
1898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  while (verneed != NULL)
1899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
1900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      size_t vna_offset = vn_offset;
1901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1902441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      vernaux = gelf_getvernaux (verneed_data,
1903441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						 vna_offset += verneed->vn_aux,
1904441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						 &vernaux_mem);
1905441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      while (vernaux != NULL
1906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     && vernaux->vna_other != *versym
1907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     && vernaux->vna_next != 0)
1908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			{
1909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  /* Update the offset.  */
1910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  vna_offset += vernaux->vna_next;
1911441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1912441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  vernaux = (vernaux->vna_next == 0
1913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     ? NULL
1914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     : gelf_getvernaux (verneed_data,
1915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project							vna_offset,
1916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project							&vernaux_mem));
1917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			}
1918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      /* Check whether we found the version.  */
1920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (vernaux != NULL && vernaux->vna_other == *versym)
1921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* Found it.  */
1922441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			break;
1923441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      vn_offset += verneed->vn_next;
1925441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      verneed = (verneed->vn_next == 0
1926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 ? NULL
1927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				 : gelf_getverneed (verneed_data, vn_offset,
1928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						    &verneed_mem));
1929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
1930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (vernaux != NULL && vernaux->vna_other == *versym)
1932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
1933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      printf ("@%s (%u)",
1934441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      elf_strptr (ebl->elf, verneed_stridx,
1935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					  vernaux->vna_name),
1936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      (unsigned int) vernaux->vna_other);
1937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      check_def = 0;
1938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
1939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  else if (unlikely (! is_nobits))
1940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    error (0, 0, gettext ("bad dynamic symbol"));
1941441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  else
1942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    check_def = 1;
1943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1944441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (check_def && *versym != 0x8001)
1946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
1947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* We must test both.  */
1948441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  size_t vd_offset = 0;
1949441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Verdef verdef_mem;
1951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0,
1952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng							&verdef_mem);
1953441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  while (verdef != NULL)
1954441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
1955441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (verdef->vd_ndx == (*versym & 0x7fff))
1956441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			/* Found the definition.  */
1957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			break;
1958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      vd_offset += verdef->vd_next;
1960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      verdef = (verdef->vd_next == 0
1961441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				? NULL
1962441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				: gelf_getverdef (verdef_data, vd_offset,
1963441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						  &verdef_mem));
1964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
1965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (verdef != NULL)
1967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    {
1968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      GElf_Verdaux verdaux_mem;
1969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      GElf_Verdaux *verdaux
1970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			= gelf_getverdaux (verdef_data,
1971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					   vd_offset + verdef->vd_aux,
1972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					   &verdaux_mem);
1973441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1974441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      if (verdaux != NULL)
1975441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			printf ((*versym & 0x8000) ? "@%s" : "@@%s",
1976441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				elf_strptr (ebl->elf, verdef_stridx,
1977441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					    verdaux->vda_name));
1978441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    }
1979441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
1980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
1981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
1982441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      putchar_unlocked ('\n');
1984441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
1985441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
1986441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1987441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1988441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print version information.  */
1989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
1990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_verinfo (Ebl *ebl)
1991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
1992441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Find the version information sections.  For this we have to
1993441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     search through the section table.  */
1994441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn = NULL;
1995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
1996441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1997441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
1998441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Handle the section if it is part of the versioning handling.  */
1999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
2000441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2001441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (shdr != NULL))
2003441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (shdr->sh_type == SHT_GNU_verneed)
2005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    handle_verneed (ebl, scn, shdr);
2006441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (shdr->sh_type == SHT_GNU_verdef)
2007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    handle_verdef (ebl, scn, shdr);
2008441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (shdr->sh_type == SHT_GNU_versym)
2009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    handle_versym (ebl, scn, shdr);
2010441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2013441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2014441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2015441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *
2016441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectget_ver_flags (unsigned int flags)
2017441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static char buf[32];
2019441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  char *endp;
2020441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2021441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (flags == 0)
2022441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return gettext ("none");
2023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2024441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (flags & VER_FLG_BASE)
2025441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    endp = stpcpy (buf, "BASE ");
2026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
2027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    endp = buf;
2028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (flags & VER_FLG_WEAK)
2030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (endp != buf)
2032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project        endp = stpcpy (endp, "| ");
2033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2034441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      endp = stpcpy (endp, "WEAK ");
2035441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
2038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
2040441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      buf[sizeof (buf) - 1] = '\0';
2041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return buf;
2044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int class = gelf_getclass (ebl->elf);
2051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
2053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
2054441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
2055441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
2056441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2057441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
2058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
2059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2060441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
2061441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
2062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr glink;
2064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext ("\
2065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2066441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
2067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr->sh_info),
2069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) elf_ndxscn (scn),
2070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
2071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr->sh_offset,
2073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) shdr->sh_link,
2074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx,
2075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    &glink)->sh_name));
2077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int offset = 0;
2079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int cnt = shdr->sh_info; --cnt >= 0; )
2080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get the data at the next offset.  */
2082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Verneed needmem;
2083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
2084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (need == NULL))
2085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
2086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
2088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      offset, (unsigned short int) need->vn_version,
2089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
2090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (unsigned short int) need->vn_cnt);
2091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      unsigned int auxoffset = offset + need->vn_aux;
2093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2095441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Vernaux auxmem;
2096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
2097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (aux == NULL))
2098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    break;
2099441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
2101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  auxoffset,
2102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
2103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  get_ver_flags (aux->vna_flags),
2104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  (unsigned short int) aux->vna_other);
2105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  auxoffset += aux->vna_next;
2107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Find the next offset.  */
2110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      offset += need->vn_next;
2111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
2119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
2120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
2121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
2122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
2124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
2125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
2127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
2128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int class = gelf_getclass (ebl->elf);
2130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr glink;
2131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext ("\
2132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
2134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
2135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr->sh_info),
2136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) elf_ndxscn (scn),
2137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr->sh_info,
2139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr->sh_offset,
2141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) shdr->sh_link,
2142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx,
2143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    &glink)->sh_name));
2145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int offset = 0;
2147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int cnt = shdr->sh_info; --cnt >= 0; )
2148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Get the data at the next offset.  */
2150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Verdef defmem;
2151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
2152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (def == NULL))
2153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
2154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      unsigned int auxoffset = offset + def->vd_aux;
2156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Verdaux auxmem;
2157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
2158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (aux == NULL))
2159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
2160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("\
2162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
2163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      offset, def->vd_version,
2164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      get_ver_flags (def->vd_flags),
2165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      def->vd_ndx,
2166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      def->vd_cnt,
2167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      auxoffset += aux->vda_next;
2170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
2171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
2173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (aux == NULL))
2174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    break;
2175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext ("  %#06x: Parent %d: %s\n"),
2177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  auxoffset, cnt2,
2178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
2179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  auxoffset += aux->vda_next;
2181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Find the next offset.  */
2184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      offset += def->vd_next;
2185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int class = gelf_getclass (ebl->elf);
2193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const char **vername;
2194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const char **filename;
2195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the data of the section.  */
2197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
2198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (data == NULL)
2199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
2200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
2202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
2203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
2205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
2206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We have to find the version definition section and extract the
2208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     version names.  */
2209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *defscn = NULL;
2210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *needscn = NULL;
2211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *verscn = NULL;
2213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
2214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr vershdr_mem;
2216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
2217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (vershdr != NULL))
2219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (vershdr->sh_type == SHT_GNU_verdef)
2221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    defscn = verscn;
2222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (vershdr->sh_type == SHT_GNU_verneed)
2223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    needscn = verscn;
2224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t nvername;
2228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (defscn != NULL || needscn != NULL)
2229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* We have a version information (better should have).  Now get
2231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 the version names.  First find the maximum version number.  */
2232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      nvername = 0;
2233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (defscn != NULL)
2234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Run through the version definitions and find the highest
2236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     index.  */
2237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int offset = 0;
2238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Data *defdata;
2239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr defshdrmem;
2240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr *defshdr;
2241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  defdata = elf_getdata (defscn, NULL);
2243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (defdata == NULL))
2244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  defshdr = gelf_getshdr (defscn, &defshdrmem);
2247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (defshdr == NULL))
2248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Verdef defmem;
2253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Verdef *def;
2254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Get the data at the next offset.  */
2256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      def = gelf_getverdef (defdata, offset, &defmem);
2257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (def == NULL))
2258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		break;
2259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
2261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      offset += def->vd_next;
2263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (needscn != NULL)
2266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int offset = 0;
2268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Data *needdata;
2269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr needshdrmem;
2270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr *needshdr;
2271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  needdata = elf_getdata (needscn, NULL);
2273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (needdata == NULL))
2274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  needshdr = gelf_getshdr (needscn, &needshdrmem);
2277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (needshdr == NULL))
2278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Verneed needmem;
2283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Verneed *need;
2284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      unsigned int auxoffset;
2285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      int cnt2;
2286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Get the data at the next offset.  */
2288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      need = gelf_getverneed (needdata, offset, &needmem);
2289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (need == NULL))
2290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		break;
2291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Run through the auxiliary entries.  */
2293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      auxoffset = offset + need->vn_aux;
2294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
2295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
2296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Vernaux auxmem;
2297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Vernaux *aux;
2298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
2300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (unlikely (aux == NULL))
2301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    break;
2302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  nvername = MAX (nvername,
2304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				  (size_t) (aux->vna_other & 0x7fff));
2305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  auxoffset += aux->vna_next;
2307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
2308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      offset += need->vn_next;
2310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* This is the number of versions we know about.  */
2314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++nvername;
2315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Allocate the array.  */
2317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      vername = (const char **) alloca (nvername * sizeof (const char *));
2318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      filename = (const char **) alloca (nvername * sizeof (const char *));
2319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Run through the data structures again and collect the strings.  */
2321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (defscn != NULL)
2322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Run through the version definitions and find the highest
2324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     index.  */
2325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int offset = 0;
2326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Data *defdata;
2327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr defshdrmem;
2328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  GElf_Shdr *defshdr;
2329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  defdata = elf_getdata (defscn, NULL);
2331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (defdata == NULL))
2332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  defshdr = gelf_getshdr (defscn, &defshdrmem);
2335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (defshdr == NULL))
2336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
2339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Get the data at the next offset.  */
2342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      GElf_Verdef defmem;
2343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
2344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      GElf_Verdaux auxmem;
2345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
2346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						   offset + def->vd_aux,
2347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						   &auxmem);
2348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (def == NULL || aux == NULL))
2349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		break;
2350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      vername[def->vd_ndx & 0x7fff]
2352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
2353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      filename[def->vd_ndx & 0x7fff] = NULL;
2354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      offset += def->vd_next;
2356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (needscn != NULL)
2359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int offset = 0;
2361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf_Data *needdata = elf_getdata (needscn, NULL);
2363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr needshdrmem;
2364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
2365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (needdata == NULL || needshdr == NULL))
2366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
2369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Get the data at the next offset.  */
2371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      GElf_Verneed needmem;
2372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
2373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						    &needmem);
2374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (need == NULL))
2375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		break;
2376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Run through the auxiliary entries.  */
2378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      unsigned int auxoffset = offset + need->vn_aux;
2379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
2380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
2381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  GElf_Vernaux auxmem;
2382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
2383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						       &auxmem);
2384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (unlikely (aux == NULL))
2385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    break;
2386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  vername[aux->vna_other & 0x7fff]
2388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
2389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  filename[aux->vna_other & 0x7fff]
2390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
2391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  auxoffset += aux->vna_next;
2393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
2394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      offset += need->vn_next;
2396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
2400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      vername = NULL;
2402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      nvername = 1;
2403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      filename = NULL;
2404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Print the header.  */
2407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr glink;
2408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext ("\
2409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
2411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
2412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    shdr->sh_size / shdr->sh_entsize),
2413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) elf_ndxscn (scn),
2414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (int) (shdr->sh_size / shdr->sh_entsize),
2416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
2417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  shdr->sh_offset,
2418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (unsigned int) shdr->sh_link,
2419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  elf_strptr (ebl->elf, shstrndx,
2420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    &glink)->sh_name));
2422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Now we can finally look at the actual contents of this section.  */
2424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
2425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (cnt % 2 == 0)
2427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	printf ("\n %4d:", cnt);
2428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Versym symmem;
2430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
2431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (sym == NULL)
2432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
2433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      switch (*sym)
2435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ssize_t n;
2437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case 0:
2438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  fputs_unlocked (gettext ("   0 *local*                     "),
2439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  stdout);
2440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case 1:
2443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  fputs_unlocked (gettext ("   1 *global*                    "),
2444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  stdout);
2445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	default:
2448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  n = printf ("%4d%c%s",
2449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
2450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      (unsigned int) (*sym & 0x7fff) < nvername
2451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      ? vername[*sym & 0x7fff] : "???");
2452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if ((unsigned int) (*sym & 0x7fff) < nvername
2453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      && filename[*sym & 0x7fff] != NULL)
2454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    n += printf ("(%s)", filename[*sym & 0x7fff]);
2455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf ("%*s", MAX (0, 33 - (int) n), " ");
2456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
2457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  putchar_unlocked ('\n');
2460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
2465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 uint_fast32_t maxlength, Elf32_Word nbucket,
2466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
2467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
2469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    ++counts[lengths[cnt]];
2472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr glink;
2474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  printf (ngettext ("\
2475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben 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",
2476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    "\
2477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben 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",
2478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    nbucket),
2479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  (unsigned int) elf_ndxscn (scn),
2480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  (int) nbucket,
2482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
2483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  shdr->sh_addr,
2484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  shdr->sh_offset,
2485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  (unsigned int) shdr->sh_link,
2486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  elf_strptr (ebl->elf, shstrndx,
2487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				    &glink)->sh_name));
2489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (extrastr != NULL)
2491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    fputs (extrastr, stdout);
2492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (nbucket > 0))
2494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint64_t success = 0;
2496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      fputs_unlocked (gettext ("\
2498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Length  Number  % of total  Coverage\n"), stdout);
2499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
2500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      counts[0], (counts[0] * 100.0) / nbucket);
2501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint64_t nzero_counts = 0;
2503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  nzero_counts += counts[cnt] * cnt;
2506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext ("\
2507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng%7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
2508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
2509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  (nzero_counts * 100.0) / nsyms);
2510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
2511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf32_Word acc = 0;
2513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
2514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
2515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  acc += cnt;
2516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  success += counts[cnt] * acc;
2517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
2518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("\
2520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Average number of tests:   successful lookup: %f\n\
2521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng                          unsuccessful lookup: %f\n"),
2522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      (double) success / (double) nzero_counts,
2523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      (double) nzero_counts / (double) nbucket);
2524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  free (counts);
2527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
2528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* This function handles the traditional System V-style hash table format.  */
2531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
2532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
2534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
2535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (data == NULL))
2536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
2537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
2538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
2539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return;
2540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
2544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
2545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
2546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast32_t maxlength = 0;
2550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast32_t nsyms = 0;
2551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
2553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf32_Word inner = bucket[cnt];
2554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while (inner > 0 && inner < nchain)
2555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
2556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ++nsyms;
2557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (maxlength < ++lengths[cnt])
2558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    ++maxlength;
2559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  inner = chain[inner];
2561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
2562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   lengths, NULL);
2566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  free (lengths);
2568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
2569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* This function handles the incorrect, System V-style hash table
2572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   format some 64-bit architectures use.  */
2573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
2574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
2576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
2577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (data == NULL))
2578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
2579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
2580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
2581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return;
2582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
2585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
2586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
2587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
2588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast32_t maxlength = 0;
2592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast32_t nsyms = 0;
2593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
2594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
2595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf64_Xword inner = bucket[cnt];
2596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while (inner > 0 && inner < nchain)
2597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
2598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ++nsyms;
2599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (maxlength < ++lengths[cnt])
2600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    ++maxlength;
2601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  inner = chain[inner];
2603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
2604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   lengths, NULL);
2608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  free (lengths);
2610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
2611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* This function handles the GNU-style hash table format.  */
2614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
2615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
2616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
2617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata (scn, NULL);
2618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (data == NULL))
2619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
2620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("cannot get data for section %d: %s"),
2621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     (int) elf_ndxscn (scn), elf_errmsg (-1));
2622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return;
2623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
2626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
2627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Next comes the size of the bitmap.  It's measured in words for
2629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
2630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     64 bit archs.  */
2631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
2632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (gelf_getclass (ebl->elf) == ELFCLASS64)
2633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    bitmask_words *= 2;
2634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
2636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
2638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
2640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
2641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
2642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						    + nbucket];
2643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Compute distribution of chain lengths.  */
2645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast32_t maxlength = 0;
2646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast32_t nsyms = 0;
2647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
2648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    if (bucket[cnt] != 0)
2649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
2650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	Elf32_Word inner = bucket[cnt] - symbias;
2651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	do
2652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
2653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    ++nsyms;
2654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (maxlength < ++lengths[cnt])
2655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ++maxlength;
2656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
2657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	while ((chain[inner++] & 1) == 0);
2658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
2659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Count bits in bitmask.  */
2661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast32_t nbits = 0;
2662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
2663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
2664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint_fast32_t word = bitmask[cnt];
2665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
2667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
2668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
2669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
2670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
2671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *str;
2674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (asprintf (&str, gettext ("\
2675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Symbol Bias: %u\n\
2676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
2677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (unsigned int) symbias,
2678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  bitmask_words * sizeof (Elf32_Word),
2679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  ((nbits * 100 + 50)
2680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   / (uint_fast32_t) (bitmask_words
2681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					      * sizeof (Elf32_Word) * 8)),
2682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (unsigned int) shift) == -1))
2683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0, gettext ("memory exhausted"));
2684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
2686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   lengths, str);
2687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  free (str);
2689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  free (lengths);
2690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
2691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Find the symbol table(s).  For this we have to search through the
2694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   section table.  */
2695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
2696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_hash (Ebl *ebl)
2697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
2698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Get the section header string table index.  */
2699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
2700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0,
2702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   gettext ("cannot get section header string table index"));
2703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *scn = NULL;
2705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
2707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Handle the section if it is a symbol table.  */
2708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr shdr_mem;
2709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (likely (shdr != NULL))
2712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
2713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (shdr->sh_type == SHT_HASH)
2714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
2715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
2716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
2717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
2718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		handle_sysv_hash (ebl, scn, shdr, shstrndx);
2719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
2720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if (shdr->sh_type == SHT_GNU_HASH)
2721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
2722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
2728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_liblist (Ebl *ebl)
2729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Find the library list sections.  For this we have to search
2731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     through the section table.  */
2732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Scn *scn = NULL;
2733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
2735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t shstrndx;
2736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
2738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
2739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
2743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
2746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
2747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  int nentries = shdr->sh_size / shdr->sh_entsize;
2748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (ngettext ("\
2749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    "\
2751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    nentries),
2753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_ndxscn (scn),
2754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  shdr->sh_offset,
2756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  nentries);
2757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Elf_Data *data = elf_getdata (scn, NULL);
2759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (data == NULL)
2760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    return;
2761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  puts (gettext ("\
2763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       Library                       Time Stamp          Checksum Version Flags"));
2764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (int cnt = 0; cnt < nentries; ++cnt)
2766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
2767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Lib lib_mem;
2768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
2769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (lib == NULL))
2770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		continue;
2771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      time_t t = (time_t) lib->l_time_stamp;
2773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      struct tm *tm = gmtime (&t);
2774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (tm == NULL))
2775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		continue;
2776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
2778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
2779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
2780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      tm->tm_hour, tm->tm_min, tm->tm_sec,
2781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      (unsigned int) lib->l_checksum,
2782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      (unsigned int) lib->l_version,
2783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      (unsigned int) lib->l_flags);
2784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
2785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
2786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
2787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
2788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
2789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
2790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
2791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
2792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Find the object attributes sections.  For this we have to search
2793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     through the section table.  */
2794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *scn = NULL;
2795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Get the section header string table index.  */
2797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
2798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
2799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0,
2800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   gettext ("cannot get section header string table index"));
2801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
2804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr shdr_mem;
2805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (shdr == NULL || shdr->sh_type != SHT_GNU_ATTRIBUTES)
2808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	continue;
2809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("\
2811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\nObject attributes section [%2zu] '%s' of %" PRIu64
2812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       " bytes at offset %#0" PRIx64 ":\n"),
2813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      elf_ndxscn (scn),
2814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      shdr->sh_size, shdr->sh_offset);
2816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
2818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (data == NULL)
2819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return;
2820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const unsigned char *p = data->d_buf;
2822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (*p++ != 'A'))
2824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return;
2825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
2827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      inline size_t left (void)
2829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
2830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return (const unsigned char *) data->d_buf + data->d_size - p;
2831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
2832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while (left () >= 4)
2834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
2835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  uint32_t len;
2836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  memcpy (&len, p, sizeof len);
2837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
2839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    CONVERT (len);
2840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (len > left ()))
2842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
2843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  const unsigned char *name = p + sizeof len;
2845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  p += len;
2846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unsigned const char *q = memchr (name, '\0', len);
2848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (q == NULL))
2849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    continue;
2850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ++q;
2851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext ("  %-13s  %4" PRIu32 "\n"), name, len);
2853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (q - name == sizeof "gnu"
2855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      && !memcmp (name, "gnu", sizeof "gnu"))
2856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    while (q < p)
2857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
2858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		const unsigned char *const sub = q;
2859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		unsigned int subsection_tag;
2861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		get_uleb128 (subsection_tag, q);
2862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (unlikely (q >= p))
2863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  break;
2864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		uint32_t subsection_len;
2866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
2867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  break;
2868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		memcpy (&subsection_len, q, sizeof subsection_len);
2870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
2872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  CONVERT (subsection_len);
2873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (unlikely (p - sub < (ptrdiff_t) subsection_len))
2875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  break;
2876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		const unsigned char *r = q + sizeof subsection_len;
2878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		q = sub + subsection_len;
2879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		switch (subsection_tag)
2881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
2882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  default:
2883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    printf (gettext ("    %-4u %12" PRIu32 "\n"),
2884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    subsection_tag, subsection_len);
2885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    break;
2886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  case 1:	/* Tag_File */
2888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    printf (gettext ("    File: %11" PRIu32 "\n"),
2889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    subsection_len);
2890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    while (r < q)
2892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      {
2893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			unsigned int tag;
2894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			get_uleb128 (tag, r);
2895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			if (unlikely (r >= q))
2896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  break;
2897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			uint64_t value = 0;
2899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			const char *string = NULL;
2900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			if (tag == 32 || (tag & 1) == 0)
2901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  {
2902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    get_uleb128 (value, r);
2903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    if (r > q)
2904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      break;
2905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  }
2906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			if (tag == 32 || (tag & 1) != 0)
2907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  {
2908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    r = memchr (r, '\0', q - r);
2909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    if (r == NULL)
2910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      break;
2911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    ++r;
2912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  }
2913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			const char *tag_name = NULL;
2915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			const char *value_name = NULL;
2916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			ebl_check_object_attribute (ebl, (const char *) name,
2917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						    tag, value,
2918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						    &tag_name, &value_name);
2919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			if (tag_name != NULL)
2921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  {
2922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    if (tag == 32)
2923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      printf (gettext ("      %s: %" PRId64 ", %s\n"),
2924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      tag_name, value, string);
2925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    else if (string == NULL && value_name == NULL)
2926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      printf (gettext ("      %s: %" PRId64 "\n"),
2927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      tag_name, value);
2928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    else
2929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      printf (gettext ("      %s: %s\n"),
2930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      tag_name, string ?: value_name);
2931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  }
2932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			else
2933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  {
2934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    assert (tag != 32);
2935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    if (string == NULL)
2936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      printf (gettext ("      %u: %" PRId64 "\n"),
2937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      tag, value);
2938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    else
2939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      printf (gettext ("      %u: %s\n"),
2940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      tag, string);
2941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  }
2942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      }
2943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
2944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
2945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
2946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
2947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
2948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic char *
2951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengformat_dwarf_addr (Dwfl_Module *dwflmod,
2952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   int address_size, Dwarf_Addr address)
2953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
2954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* See if there is a name we can give for this address.  */
2955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Sym sym;
2956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *name = dwfl_module_addrsym (dwflmod, address, &sym, NULL);
2957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (name != NULL)
2958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    sym.st_value = address - sym.st_value;
2959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Relativize the address.  */
2961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int n = dwfl_module_relocations (dwflmod);
2962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
2963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* In an ET_REL file there is a section name to refer to.  */
2965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *scn = (i < 0 ? NULL
2966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     : dwfl_module_relocation_info (dwflmod, i, NULL));
2967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
2968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *result;
2969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((name != NULL
2970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng       ? (sym.st_value != 0
2971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ? (scn != NULL
2972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     ? (address_size == 0
2973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		? asprintf (&result,
2974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
2975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    scn, address, name, sym.st_value)
2976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		: asprintf (&result,
2977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
2978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    scn, 2 + address_size * 2, address,
2979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    name, sym.st_value))
2980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     : (address_size == 0
2981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		? asprintf (&result,
2982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
2983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    address, name, sym.st_value)
2984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		: asprintf (&result,
2985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
2986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    2 + address_size * 2, address,
2987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    name, sym.st_value)))
2988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  : (scn != NULL
2989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     ? (address_size == 0
2990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		? asprintf (&result,
2991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%s+%#" PRIx64 " <%s>"),
2992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    scn, address, name)
2993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		: asprintf (&result,
2994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%s+%#0*" PRIx64 " <%s>"),
2995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    scn, 2 + address_size * 2, address, name))
2996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     : (address_size == 0
2997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		? asprintf (&result,
2998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%#" PRIx64 " <%s>"),
2999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    address, name)
3000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		: asprintf (&result,
3001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    gettext ("%#0*" PRIx64 " <%s>"),
3002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    2 + address_size * 2, address, name))))
3003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng       : (scn != NULL
3004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ? (address_size == 0
3005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     ? asprintf (&result,
3006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 gettext ("%s+%#" PRIx64),
3007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 scn, address)
3008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     : asprintf (&result,
3009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 gettext ("%s+%#0*" PRIx64),
3010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 scn, 2 + address_size * 2, address))
3011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  : (address_size == 0
3012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     ? asprintf (&result,
3013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 "%#" PRIx64,
3014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 address)
3015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     : asprintf (&result,
3016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 "%#0*" PRIx64,
3017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 2 + address_size * 2, address)))) < 0)
3018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0, _("memory exhausted"));
3019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return result;
3021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_tag_string (unsigned int tag)
3025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known_tags[]  =
3027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_array_type] = "array_type",
3029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_class_type] = "class_type",
3030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_entry_point] = "entry_point",
3031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_enumeration_type] = "enumeration_type",
3032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_formal_parameter] = "formal_parameter",
3033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_imported_declaration] = "imported_declaration",
3034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_label] = "label",
3035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_lexical_block] = "lexical_block",
3036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_member] = "member",
3037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_pointer_type] = "pointer_type",
3038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_reference_type] = "reference_type",
3039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_compile_unit] = "compile_unit",
3040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_string_type] = "string_type",
3041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_structure_type] = "structure_type",
3042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_subroutine_type] = "subroutine_type",
3043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_typedef] = "typedef",
3044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_union_type] = "union_type",
3045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_unspecified_parameters] = "unspecified_parameters",
3046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_variant] = "variant",
3047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_common_block] = "common_block",
3048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_common_inclusion] = "common_inclusion",
3049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_inheritance] = "inheritance",
3050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_inlined_subroutine] = "inlined_subroutine",
3051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_module] = "module",
3052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
3053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_set_type] = "set_type",
3054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_subrange_type] = "subrange_type",
3055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_with_stmt] = "with_stmt",
3056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_access_declaration] = "access_declaration",
3057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_base_type] = "base_type",
3058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_catch_block] = "catch_block",
3059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_const_type] = "const_type",
3060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_constant] = "constant",
3061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_enumerator] = "enumerator",
3062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_file_type] = "file_type",
3063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_friend] = "friend",
3064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_namelist] = "namelist",
3065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_namelist_item] = "namelist_item",
3066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_packed_type] = "packed_type",
3067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_subprogram] = "subprogram",
3068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_template_type_parameter] = "template_type_parameter",
3069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_template_value_parameter] = "template_value_parameter",
3070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_TAG_thrown_type] = "thrown_type",
3071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_TAG_try_block] = "try_block",
3072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_TAG_variant_part] = "variant_part",
3073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_TAG_variable] = "variable",
3074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_TAG_volatile_type] = "volatile_type",
3075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_dwarf_procedure] = "dwarf_procedure",
3076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_restrict_type] = "restrict_type",
3077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_interface_type] = "interface_type",
3078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_namespace] = "namespace",
3079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_imported_module] = "imported_module",
3080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_unspecified_type] = "unspecified_type",
3081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_partial_unit] = "partial_unit",
3082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_imported_unit] = "imported_unit",
3083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_mutable_type] = "mutable_type",
3084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_condition] = "condition",
3085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_TAG_shared_type] = "shared_type",
3086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
3087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const unsigned int nknown_tags = (sizeof (known_tags)
3088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    / sizeof (known_tags[0]));
3089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static char buf[40];
3090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const char *result = NULL;
3091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (tag < nknown_tags))
3093441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    result = known_tags[tag];
3094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (result == NULL))
3096441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* There are a few known extensions.  */
3097441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    switch (tag)
3098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
3099441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_TAG_MIPS_loop:
3100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_loop";
3101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_TAG_format_label:
3104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "format_label";
3105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_TAG_function_template:
3108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "function_template";
3109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_TAG_class_template:
3112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "class_template";
3113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      default:
3116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (tag < DW_TAG_lo_user)
3117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
3118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	else
3119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
3120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = buf;
3121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
3123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
3125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
3126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *
3129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectdwarf_attr_string (unsigned int attrnum)
3130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
3131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known_attrs[] =
3132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
3133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_sibling] = "sibling",
3134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_location] = "location",
3135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_name] = "name",
3136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_ordering] = "ordering",
3137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_subscr_data] = "subscr_data",
3138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_byte_size] = "byte_size",
3139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_bit_offset] = "bit_offset",
3140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_bit_size] = "bit_size",
3141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_element_list] = "element_list",
3142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_stmt_list] = "stmt_list",
3143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_low_pc] = "low_pc",
3144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_high_pc] = "high_pc",
3145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_language] = "language",
3146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_member] = "member",
3147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_discr] = "discr",
3148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_discr_value] = "discr_value",
3149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_visibility] = "visibility",
3150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_import] = "import",
3151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_string_length] = "string_length",
3152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_common_reference] = "common_reference",
3153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_comp_dir] = "comp_dir",
3154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_const_value] = "const_value",
3155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_containing_type] = "containing_type",
3156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_default_value] = "default_value",
3157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_inline] = "inline",
3158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_is_optional] = "is_optional",
3159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_lower_bound] = "lower_bound",
3160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_producer] = "producer",
3161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_prototyped] = "prototyped",
3162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_return_addr] = "return_addr",
3163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_start_scope] = "start_scope",
3164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_bit_stride] = "bit_stride",
3165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_upper_bound] = "upper_bound",
3166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_abstract_origin] = "abstract_origin",
3167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_accessibility] = "accessibility",
3168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_address_class] = "address_class",
3169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_artificial] = "artificial",
3170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_base_types] = "base_types",
3171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_calling_convention] = "calling_convention",
3172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_count] = "count",
3173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_data_member_location] = "data_member_location",
3174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_decl_column] = "decl_column",
3175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_decl_file] = "decl_file",
3176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_decl_line] = "decl_line",
3177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_declaration] = "declaration",
3178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_discr_list] = "discr_list",
3179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_encoding] = "encoding",
3180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_external] = "external",
3181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_frame_base] = "frame_base",
3182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_friend] = "friend",
3183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_identifier_case] = "identifier_case",
3184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_macro_info] = "macro_info",
3185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_namelist_item] = "namelist_item",
3186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_priority] = "priority",
3187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_segment] = "segment",
3188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_specification] = "specification",
3189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_static_link] = "static_link",
3190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_type] = "type",
3191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_use_location] = "use_location",
3192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_variable_parameter] = "variable_parameter",
3193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_AT_virtuality] = "virtuality",
3194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_vtable_elem_location] = "vtable_elem_location",
3195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_allocated] = "allocated",
3196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_associated] = "associated",
3197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_data_location] = "data_location",
3198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_byte_stride] = "byte_stride",
3199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_entry_pc] = "entry_pc",
3200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_use_UTF8] = "use_UTF8",
3201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_extension] = "extension",
3202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_ranges] = "ranges",
3203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_trampoline] = "trampoline",
3204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_call_column] = "call_column",
3205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_call_file] = "call_file",
3206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_call_line] = "call_line",
3207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_description] = "description",
3208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_binary_scale] = "binary_scale",
3209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_decimal_scale] = "decimal_scale",
3210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_small] = "small",
3211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_decimal_sign] = "decimal_sign",
3212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_digit_count] = "digit_count",
3213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_picture_string] = "picture_string",
3214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_mutable] = "mutable",
3215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_threads_scaled] = "threads_scaled",
3216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_explicit] = "explicit",
3217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_object_pointer] = "object_pointer",
3218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_endianity] = "endianity",
3219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_elemental] = "elemental",
3220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_pure] = "pure",
3221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_AT_recursive] = "recursive",
3222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
3223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const unsigned int nknown_attrs = (sizeof (known_attrs)
3224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     / sizeof (known_attrs[0]));
3225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static char buf[40];
3226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const char *result = NULL;
3227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (attrnum < nknown_attrs))
3229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    result = known_attrs[attrnum];
3230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (result == NULL))
3232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* There are a few known extensions.  */
3233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    switch (attrnum)
3234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      {
3235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_fde:
3236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_fde";
3237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_loop_begin:
3240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_loop_begin";
3241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_tail_loop_begin:
3244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_tail_loop_begin";
3245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_epilog_begin:
3248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_epilog_begin";
3249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_loop_unroll_factor:
3252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_loop_unroll_factor";
3253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_software_pipeline_depth:
3256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_software_pipeline_depth";
3257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_linkage_name:
3260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_linkage_name";
3261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_stride:
3264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_stride";
3265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_abstract_name:
3268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_abstract_name";
3269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_clone_origin:
3272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_clone_origin";
3273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_has_inlines:
3276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_has_inlines";
3277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_stride_byte:
3280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_stride_byte";
3281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_stride_elem:
3284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_stride_elem";
3285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_ptr_dopetype:
3288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_ptr_dopetype";
3289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_allocatable_dopetype:
3292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_allocatable_dopetype";
3293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_assumed_shape_dopetype:
3296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_assumed_shape_dopetype";
3297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_MIPS_assumed_size:
3300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "MIPS_assumed_size";
3301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_sf_names:
3304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "sf_names";
3305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_src_info:
3308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "src_info";
3309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_mac_info:
3312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "mac_info";
3313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_src_coords:
3316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "src_coords";
3317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_body_begin:
3320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "body_begin";
3321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      case DW_AT_body_end:
3324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = "body_end";
3325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      default:
3328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	if (attrnum < DW_AT_lo_user)
3329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
3330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    attrnum);
3331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	else
3332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
3333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    attrnum);
3334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	result = buf;
3335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	break;
3336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      }
3337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
3339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
3340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *
3343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectdwarf_form_string (unsigned int form)
3344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
3345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known_forms[] =
3346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
3347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_addr] = "addr",
3348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_block2] = "block2",
3349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_block4] = "block4",
3350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_data2] = "data2",
3351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_data4] = "data4",
3352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_data8] = "data8",
3353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_string] = "string",
3354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_block] = "block",
3355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_block1] = "block1",
3356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_data1] = "data1",
3357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_flag] = "flag",
3358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_sdata] = "sdata",
3359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_strp] = "strp",
3360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_udata] = "udata",
3361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_ref_addr] = "ref_addr",
3362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_ref1] = "ref1",
3363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_ref2] = "ref2",
3364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_ref4] = "ref4",
3365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_ref8] = "ref8",
3366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_ref_udata] = "ref_udata",
3367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_FORM_indirect] = "indirect"
3368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
3369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const unsigned int nknown_forms = (sizeof (known_forms)
3370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				     / sizeof (known_forms[0]));
3371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  static char buf[40];
3372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const char *result = NULL;
3373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (form < nknown_forms))
3375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    result = known_forms[form];
3376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (result == NULL))
3378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64),
3379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (uint64_t) form);
3380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
3382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
3383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *
3386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectdwarf_lang_string (unsigned int lang)
3387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
3388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
3390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_C89] = "ISO C89",
3391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_C] = "C",
3392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Ada83] = "Ada83",
3393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_LANG_C_plus_plus] = "C++",
3394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Cobol74] = "Cobol74",
3395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Cobol85] = "Cobol85",
3396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Fortran77] = "Fortran77",
3397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Fortran90] = "Fortran90",
3398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Pascal83] = "Pascal83",
3399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Modula2] = "Modula2",
3400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Java] = "Java",
3401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_C99] = "ISO C99",
3402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Ada95] = "Ada95",
3403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_LANG_Fortran95] = "Fortran95",
3404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_LANG_PL1] = "PL1",
3405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_LANG_Objc] = "Objective C",
3406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_LANG_ObjC_plus_plus] = "Objective C++",
3407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_LANG_UPC] = "UPC",
3408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_LANG_D] = "D",
3409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
3410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (lang < sizeof (known) / sizeof (known[0])))
3412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return known[lang];
3413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else if (lang == DW_LANG_Mips_Assembler)
3414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* This language tag is used for assembler in general.  */
3415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return "Assembler";
3416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
3418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
3419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      static char buf[30];
3420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
3421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return buf;
3422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
3423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return "???";
3425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
3426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_inline_string (unsigned int code)
3430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_INL_not_inlined] = "not_inlined",
3434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_INL_inlined] = "inlined",
3435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_INL_declared_not_inlined] = "declared_not_inlined",
3436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_INL_declared_inlined] = "declared_inlined"
3437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_encoding_string (unsigned int code)
3448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_void] = "void",
3452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_address] = "address",
3453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_boolean] = "boolean",
3454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_complex_float] = "complex_float",
3455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_float] = "float",
3456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_signed] = "signed",
3457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_signed_char] = "signed_char",
3458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_unsigned] = "unsigned",
3459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_unsigned_char] = "unsigned_char",
3460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_imaginary_float] = "imaginary_float",
3461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_packed_decimal] = "packed_decimal",
3462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_numeric_string] = "numeric_string",
3463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_edited] = "edited",
3464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_signed_fixed] = "signed_fixed",
3465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_unsigned_fixed] = "unsigned_fixed",
3466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ATE_decimal_float] = "decimal_float",
3467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
3473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      static char buf[30];
3475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
3476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return buf;
3477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
3478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_access_string (unsigned int code)
3485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ACCESS_public] = "public",
3489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ACCESS_protected] = "protected",
3490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ACCESS_private] = "private"
3491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_visibility_string (unsigned int code)
3502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_VIS_local] = "local",
3506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_VIS_exported] = "exported",
3507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_VIS_qualified] = "qualified"
3508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_virtuality_string (unsigned int code)
3519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_VIRTUALITY_none] = "none",
3523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_VIRTUALITY_virtual] = "virtual",
3524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_VIRTUALITY_pure_virtual] = "pure_virtual"
3525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_identifier_case_string (unsigned int code)
3536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ID_case_sensitive] = "sensitive",
3540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ID_up_case] = "up_case",
3541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ID_down_case] = "down_case",
3542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ID_case_insensitive] = "insensitive"
3543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_calling_convention_string (unsigned int code)
3554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_CC_normal] = "normal",
3558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_CC_program] = "program",
3559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_CC_nocall] = "nocall",
3560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (code >= DW_CC_lo_user && code <= DW_CC_hi_user)
3566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      static char buf[30];
3568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user);
3569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return buf;
3570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
3571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_ordering_string (unsigned int code)
3578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ORD_row_major] = "row_major",
3582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_ORD_col_major] = "col_major"
3583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char *
3593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwarf_discr_list_string (unsigned int code)
3594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
3595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
3597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_DSC_label] = "label",
3598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_DSC_range] = "range"
3599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
3600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (code < sizeof (known) / sizeof (known[0])))
3602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return known[code];
3603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return "???";
3605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
3606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
3609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
3610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   unsigned int addrsize, Dwarf_Word len, const unsigned char *data)
3611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
3612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  static const char *const known[] =
3613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
3614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_addr] = "addr",
3615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_deref] = "deref",
3616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const1u] = "const1u",
3617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const1s] = "const1s",
3618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const2u] = "const2u",
3619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const2s] = "const2s",
3620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const4u] = "const4u",
3621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const4s] = "const4s",
3622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const8u] = "const8u",
3623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_const8s] = "const8s",
3624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_constu] = "constu",
3625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_consts] = "consts",
3626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_dup] = "dup",
3627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_drop] = "drop",
3628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_over] = "over",
3629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_pick] = "pick",
3630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_swap] = "swap",
3631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_rot] = "rot",
3632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_xderef] = "xderef",
3633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_abs] = "abs",
3634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_and] = "and",
3635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_div] = "div",
3636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_minus] = "minus",
3637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_mod] = "mod",
3638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_mul] = "mul",
3639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_neg] = "neg",
3640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_not] = "not",
3641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_or] = "or",
3642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_plus] = "plus",
3643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_plus_uconst] = "plus_uconst",
3644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_shl] = "shl",
3645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_shr] = "shr",
3646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_shra] = "shra",
3647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_xor] = "xor",
3648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_bra] = "bra",
3649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_eq] = "eq",
3650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_ge] = "ge",
3651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_gt] = "gt",
3652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_le] = "le",
3653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lt] = "lt",
3654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_ne] = "ne",
3655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_skip] = "skip",
3656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit0] = "lit0",
3657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit1] = "lit1",
3658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit2] = "lit2",
3659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit3] = "lit3",
3660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit4] = "lit4",
3661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit5] = "lit5",
3662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit6] = "lit6",
3663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit7] = "lit7",
3664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit8] = "lit8",
3665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit9] = "lit9",
3666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit10] = "lit10",
3667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit11] = "lit11",
3668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit12] = "lit12",
3669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit13] = "lit13",
3670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit14] = "lit14",
3671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit15] = "lit15",
3672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit16] = "lit16",
3673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit17] = "lit17",
3674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit18] = "lit18",
3675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit19] = "lit19",
3676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit20] = "lit20",
3677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit21] = "lit21",
3678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit22] = "lit22",
3679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit23] = "lit23",
3680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit24] = "lit24",
3681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit25] = "lit25",
3682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit26] = "lit26",
3683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit27] = "lit27",
3684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit28] = "lit28",
3685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit29] = "lit29",
3686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit30] = "lit30",
3687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_lit31] = "lit31",
3688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg0] = "reg0",
3689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg1] = "reg1",
3690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg2] = "reg2",
3691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg3] = "reg3",
3692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg4] = "reg4",
3693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg5] = "reg5",
3694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg6] = "reg6",
3695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg7] = "reg7",
3696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg8] = "reg8",
3697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg9] = "reg9",
3698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg10] = "reg10",
3699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg11] = "reg11",
3700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg12] = "reg12",
3701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg13] = "reg13",
3702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg14] = "reg14",
3703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg15] = "reg15",
3704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg16] = "reg16",
3705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg17] = "reg17",
3706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg18] = "reg18",
3707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg19] = "reg19",
3708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg20] = "reg20",
3709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg21] = "reg21",
3710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg22] = "reg22",
3711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg23] = "reg23",
3712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg24] = "reg24",
3713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg25] = "reg25",
3714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg26] = "reg26",
3715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg27] = "reg27",
3716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg28] = "reg28",
3717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg29] = "reg29",
3718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg30] = "reg30",
3719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_reg31] = "reg31",
3720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg0] = "breg0",
3721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg1] = "breg1",
3722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg2] = "breg2",
3723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg3] = "breg3",
3724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg4] = "breg4",
3725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg5] = "breg5",
3726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg6] = "breg6",
3727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg7] = "breg7",
3728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg8] = "breg8",
3729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg9] = "breg9",
3730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg10] = "breg10",
3731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg11] = "breg11",
3732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg12] = "breg12",
3733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg13] = "breg13",
3734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg14] = "breg14",
3735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg15] = "breg15",
3736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg16] = "breg16",
3737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg17] = "breg17",
3738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg18] = "breg18",
3739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg19] = "breg19",
3740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg20] = "breg20",
3741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg21] = "breg21",
3742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg22] = "breg22",
3743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg23] = "breg23",
3744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg24] = "breg24",
3745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg25] = "breg25",
3746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg26] = "breg26",
3747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg27] = "breg27",
3748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg28] = "breg28",
3749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg29] = "breg29",
3750441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg30] = "breg30",
3751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_breg31] = "breg31",
3752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_regx] = "regx",
3753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_fbreg] = "fbreg",
3754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_bregx] = "bregx",
3755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_piece] = "piece",
3756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_deref_size] = "deref_size",
3757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_xderef_size] = "xderef_size",
3758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_nop] = "nop",
3759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_push_object_address] = "push_object_address",
3760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_call2] = "call2",
3761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_call4] = "call4",
3762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      [DW_OP_call_ref] = "call_ref",
3763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_OP_form_tls_address] = "form_tls_address",
3764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_OP_call_frame_cfa] = "call_frame_cfa",
3765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      [DW_OP_bit_piece] = "bit_piece",
3766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    };
3767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Word offset = 0;
3769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (len-- > 0)
3770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
3771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint_fast8_t op = *data++;
3772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      switch (op)
3774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
3775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_call_ref:
3776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_addr:;
3777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Address operand.  */
3778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Dwarf_Word addr;
3779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (addrsize == 4)
3780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    addr = read_4ubyte_unaligned (dbg, data);
3781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
3782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
3783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      assert (addrsize == 8);
3784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      addr = read_8ubyte_unaligned (dbg, data);
3785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
3786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += addrsize;
3787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= addrsize;
3788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (op == DW_OP_addr)
3790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
3791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      char *a = format_dwarf_addr (dwflmod, 0, addr);
3792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      printf ("%*s[%4" PRIuMAX "] %s %s\n",
3793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      indent, "", (uintmax_t) offset,
3794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      known[op] ?: "???", a);
3795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      free (a);
3796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
3797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
3798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
3799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    indent, "", (uintmax_t) offset,
3800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    known[op] ?: "???", (uintmax_t) addr);
3801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 1 + addrsize;
3802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_OP_deref_size:
3805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_OP_xderef_size:
3806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_pick:
3807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const1u:
3808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
3809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", *((uint8_t *) data));
3811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ++data;
3812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  --len;
3813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 2;
3814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const2u:
3817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
3818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
3820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= 2;
3821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += 2;
3822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 3;
3823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const4u:
3826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
3827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
3829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= 4;
3830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += 4;
3831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 5;
3832441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3833441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const8u:
3835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
3836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
3838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= 8;
3839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += 8;
3840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 9;
3841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const1s:
3844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
3845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", *((int8_t *) data));
3847441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ++data;
3848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  --len;
3849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 2;
3850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const2s:
3853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
3854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
3856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= 2;
3857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += 2;
3858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 3;
3859441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const4s:
3862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
3863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
3865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= 4;
3866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += 4;
3867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 5;
3868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3870441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_const8s:
3871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
3872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
3874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= 8;
3875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += 8;
3876441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 9;
3877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_OP_piece:
3880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_regx:
3881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_plus_uconst:
3882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_constu:;
3883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  const unsigned char *start = data;
3884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int uleb;
3885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (uleb, data);
3886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %u\n",
3887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", uleb);
3889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= data - start;
3890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 1 + (data - start);
3891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_OP_bit_piece:
3894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  start = data;
3895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unsigned int uleb2;
3896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  get_uleb128 (uleb, data);
3897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  get_uleb128 (uleb2, data);
3898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %u, %u\n",
3899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  known[op] ?: "???", uleb, uleb2);
3901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  len -= data - start;
3902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  offset += 1 + (data - start);
3903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
3904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3905441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_fbreg:
3906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_breg0 ... DW_OP_breg31:
3907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_consts:
3908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  start = data;
3909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int sleb;
3910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_sleb128 (sleb, data);
3911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %d\n",
3912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", sleb);
3914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= data - start;
3915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 1 + (data - start);
3916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_bregx:
3919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  start = data;
3920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (uleb, data);
3921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_sleb128 (sleb, data);
3922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %u %d\n",
3923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???", uleb, sleb);
3925441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= data - start;
3926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 1 + (data - start);
3927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_call2:
3930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_call4:
3931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_skip:
3932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_OP_bra:
3933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
3934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  indent, "", (uintmax_t) offset,
3935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  known[op] ?: "???",
3936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
3937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  len -= 2;
3938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  data += 2;
3939441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  offset += 3;
3940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3941441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	default:
3943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* No Operand.  */
3944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (op < sizeof known / sizeof known[0] && known[op] != NULL)
3945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("%*s[%4" PRIuMAX "] %s\n",
3946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    indent, "", (uintmax_t) offset, known[op]);
3947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
3948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("%*s[%4" PRIuMAX "] %#x\n",
3949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    indent, "", (uintmax_t) offset, op);
3950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ++offset;
3951441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
3952441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
3953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
3954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      indent = indentrest;
3955441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
3956441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
3957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
3960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
3961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    Ebl *ebl __attribute__ ((unused)),
3962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    GElf_Ehdr *ehdr __attribute__ ((unused)),
3963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    Elf_Scn *scn __attribute__ ((unused)),
3964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    GElf_Shdr *shdr, Dwarf *dbg)
3965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
3966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
3967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   " [ Code]\n"),
3968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_abbrev", (uint64_t) shdr->sh_offset);
3969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3970441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off offset = 0;
3971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while (offset < shdr->sh_size)
3972441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
3973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"),
3974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      offset);
3975441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while (1)
3977441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
3978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t length;
3979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Dwarf_Abbrev abbrev;
3980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
3982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (res != 0)
3983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
3984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (res < 0))
3985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
3986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  printf (gettext ("\
3987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *** error while reading abbreviation: %s\n"),
3988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  dwarf_errmsg (-1));
3989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  return;
3990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
3991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* This is the NUL byte at the end of the section.  */
3993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ++offset;
3994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break;
3995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
3996441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
3997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* We know these calls can never fail.  */
3998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unsigned int code = dwarf_getabbrevcode (&abbrev);
3999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
4000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int has_children = dwarf_abbrevhaschildren (&abbrev);
4001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext (" [%5u] offset: %" PRId64
4003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   ", children: %s, tag: %s\n"),
4004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  code, (int64_t) offset,
4005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  has_children ? gettext ("yes") : gettext ("no"),
4006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  dwarf_tag_string (tag));
4007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t cnt = 0;
4009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unsigned int name;
4010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unsigned int form;
4011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Dwarf_Off enoffset;
4012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  while (dwarf_getabbrevattr (&abbrev, cnt,
4013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      &name, &form, &enoffset) == 0)
4014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
4015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
4016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      dwarf_attr_string (name), dwarf_form_string (form),
4017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      (uint64_t) enoffset);
4018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ++cnt;
4020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
4021441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  offset += length;
4023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4024441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4025441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
4026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print content of DWARF .debug_aranges section.  We fortunately do
4029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   not have to know a bit about the structure of the section, libdwarf
4030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   takes care of it.  */
4031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
4032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     Ebl *ebl __attribute__ ((unused)),
4034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     GElf_Ehdr *ehdr __attribute__ ((unused)),
4035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     Elf_Scn *scn __attribute__ ((unused)),
4036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			     GElf_Shdr *shdr, Dwarf *dbg)
4037441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
4038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Aranges *aranges;
4039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cnt;
4040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
4041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
4043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     dwarf_errmsg (-1));
4044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
4045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (ngettext ("\
4048441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
4049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    "\
4050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
4051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    cnt),
4052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
4053441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4054441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Compute floor(log16(cnt)).  */
4055441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t tmp = cnt;
4056441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int digits = 1;
4057441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (tmp >= 16)
4058441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++digits;
4060441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      tmp >>= 4;
4061441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4063441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  for (size_t n = 0; n < cnt; ++n)
4064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Arange *runp = dwarf_onearange (aranges, n);
4066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (runp == NULL))
4067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
4069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  return;
4070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Addr start;
4073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Word length;
4074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Off offset;
4075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
4077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	printf (gettext (" [%*zu] ???\n"), digits, n);
4078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
4079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	printf (gettext (" [%*zu] start: %0#*" PRIx64
4080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 ", length: %5" PRIu64 ", CU DIE offset: %6"
4081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 PRId64 "\n"),
4082441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
4083441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		(uint64_t) start, (uint64_t) length, (int64_t) offset);
4084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
4086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Print content of DWARF .debug_ranges section.  */
4088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
4089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_ranges_section (Dwfl_Module *dwflmod,
4090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    Ebl *ebl __attribute__ ((unused)),
4091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr,
4092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    Dwarf *dbg)
4093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
4094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
4095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (data == NULL))
4097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
4098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
4099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     elf_errmsg (-1));
4100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return;
4101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
4102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  printf (gettext ("\
4104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ".debug_ranges", (uint64_t) shdr->sh_offset);
4106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool first = true;
4110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned char *readp = data->d_buf;
4111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while (readp < (unsigned char *) data->d_buf + data->d_size)
4112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
4113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (data->d_size - offset < address_size * 2))
4116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
4118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Dwarf_Addr begin;
4122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Dwarf_Addr end;
4123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (address_size == 8)
4124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  begin = read_8ubyte_unaligned_inc (dbg, readp);
4126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  end = read_8ubyte_unaligned_inc (dbg, readp);
4127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
4129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  begin = read_4ubyte_unaligned_inc (dbg, readp);
4131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  end = read_4ubyte_unaligned_inc (dbg, readp);
4132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (begin == (Dwarf_Addr) (uint32_t) -1)
4133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    begin = (Dwarf_Addr) -1l;
4134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
4137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, end);
4139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
4140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  free (b);
4141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else if (begin == 0 && end == 0) /* End of list entry.  */
4143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	first = true;
4144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
4145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
4147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *e = format_dwarf_addr (dwflmod, address_size, end);
4148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* We have an address range entry.  */
4149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (first)		/* First address range entry in a list.  */
4150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf (gettext (" [%6tx]  %s..%s\n"), offset, b, e);
4151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
4152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf (gettext ("           %s..%s\n"), b, e);
4153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  free (b);
4154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  free (e);
4155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  first = false;
4157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
4159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
4160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
4163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_frame_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
4164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   Ebl *ebl __attribute__ ((unused)),
4165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   GElf_Ehdr *ehdr __attribute__ ((unused)),
4166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   Elf_Scn *scn __attribute__ ((unused)),
4167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   GElf_Shdr *shdr __attribute__ ((unused)),
4168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   Dwarf *dbg __attribute__ ((unused)))
4169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
4170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
4171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstruct attrcb_args
4174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
4175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Dwfl_Module *dwflmod;
4176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf *dbg;
4177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int level;
4178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  unsigned int addrsize;
4179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off cu_offset;
4180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
4181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
4184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectattr_callback (Dwarf_Attribute *attrp, void *arg)
4185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
4186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct attrcb_args *cbargs = (struct attrcb_args *) arg;
4187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const int level = cbargs->level;
4188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  unsigned int attr = dwarf_whatattr (attrp);
4190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (attr == 0))
4191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot get attribute code: %s"),
4193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     dwarf_errmsg (-1));
4194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return DWARF_CB_ABORT;
4195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  unsigned int form = dwarf_whatform (attrp);
4198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (form == 0))
4199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot get attribute form: %s"),
4201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     dwarf_errmsg (-1));
4202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return DWARF_CB_ABORT;
4203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  switch (form)
4206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case DW_FORM_addr:
4208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
4209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	Dwarf_Addr addr;
4210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
4211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
4212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  attrval_out:
4213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    error (0, 0, gettext ("cannot get attribute value: %s"),
4214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   dwarf_errmsg (-1));
4215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    return DWARF_CB_ABORT;
4216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
4217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
4218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	printf ("           %*s%-20s %s\n",
4219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		(int) (level * 2), "", dwarf_attr_string (attr), a);
4220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	free (a);
4221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
4222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
4223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_indirect:
4225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_strp:
4226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_string:;
4227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      const char *str = dwarf_formstring (attrp);
4228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (str == NULL))
4229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	goto attrval_out;
4230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("           %*s%-20s \"%s\"\n",
4231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (int) (level * 2), "", dwarf_attr_string (attr), str);
4232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
4233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_ref_addr:
4235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_ref_udata:
4236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_ref8:
4237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_ref4:
4238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_ref2:
4239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_ref1:;
4240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Dwarf_Die ref;
4241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
4242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	goto attrval_out;
4243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4244441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("           %*s%-20s [%6" PRIxMAX "]\n",
4245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (int) (level * 2), "", dwarf_attr_string (attr),
4246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      (uintmax_t) dwarf_dieoffset (&ref));
4247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
4248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_udata:
4250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_sdata:
4251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_data8:
4252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_data4:
4253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_data2:
4254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_data1:;
4255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Word num;
4256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (dwarf_formudata (attrp, &num) != 0))
4257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	goto attrval_out;
4258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *valuestr = NULL;
4260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      switch (attr)
4261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_location:
4263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_data_location:
4264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_data_member_location:
4265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_vtable_elem_location:
4266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_string_length:
4267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_use_location:
4268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_frame_base:
4269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_return_addr:
4270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_static_link:
4271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("           %*s%-20s location list [%6" PRIxMAX "]\n",
4272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  (int) (level * 2), "", dwarf_attr_string (attr),
4273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  (uintmax_t) num);
4274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  return DWARF_CB_OK;
4275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_ranges:
4277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("           %*s%-20s range list [%6" PRIxMAX "]\n",
4278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  (int) (level * 2), "", dwarf_attr_string (attr),
4279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  (uintmax_t) num);
4280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  return DWARF_CB_OK;
4281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_language:
4283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_lang_string (num);
4284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_encoding:
4286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_encoding_string (num);
4287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_accessibility:
4289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_access_string (num);
4290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_visibility:
4292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_visibility_string (num);
4293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_virtuality:
4295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_virtuality_string (num);
4296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_identifier_case:
4298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_identifier_case_string (num);
4299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_calling_convention:
4301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_calling_convention_string (num);
4302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_inline:
4304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_inline_string (num);
4305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_ordering:
4307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_ordering_string (num);
4308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_discr_list:
4310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  valuestr = dwarf_discr_list_string (num);
4311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	default:
4313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Nothing.  */
4314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
4315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (valuestr == NULL)
4318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	printf ("           %*s%-20s %" PRIuMAX "\n",
4319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		(int) (level * 2), "", dwarf_attr_string (attr),
4320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		(uintmax_t) num);
4321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
4322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	printf ("           %*s%-20s %s (%" PRIuMAX ")\n",
4323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		(int) (level * 2), "", dwarf_attr_string (attr),
4324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		valuestr, (uintmax_t) num);
4325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
4326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_flag:;
4328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      bool flag;
4329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (dwarf_formflag (attrp, &flag) != 0))
4330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	goto attrval_out;
4331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("           %*s%-20s %s\n",
4333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (int) (level * 2), "", dwarf_attr_string (attr),
4334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      nl_langinfo (flag ? YESSTR : NOSTR));
4335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
4336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_block4:
4338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_block2:
4339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_block1:
4340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    case DW_FORM_block:;
4341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Block block;
4342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (dwarf_formblock (attrp, &block) != 0))
4343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	goto attrval_out;
4344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("           %*s%-20s %" PRIxMAX " byte block\n",
4346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (int) (level * 2), "", dwarf_attr_string (attr),
4347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (uintmax_t) block.length);
4348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      switch (attr)
4350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_location:
4352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_data_location:
4353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_data_member_location:
4354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_vtable_elem_location:
4355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_string_length:
4356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_use_location:
4357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_frame_base:
4358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_return_addr:
4359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_static_link:
4360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_allocated:
4361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_associated:
4362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_bit_size:
4363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_bit_offset:
4364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_bit_stride:
4365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_byte_size:
4366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_byte_stride:
4367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_count:
4368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_lower_bound:
4369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_AT_upper_bound:
4370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  print_ops (cbargs->dwflmod, cbargs->dbg,
4371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     12 + level * 2, 12 + level * 2,
4372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     cbargs->addrsize, block.length, block.data);
4373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
4376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    default:
4378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf ("           %*s%-20s [form: %d] ???\n",
4379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (int) (level * 2), "", dwarf_attr_string (attr),
4380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (int) form);
4381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      break;
4382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return DWARF_CB_OK;
4385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
4386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
4389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_info_section (Dwfl_Module *dwflmod,
4390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  Ebl *ebl __attribute__ ((unused)),
4391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  GElf_Ehdr *ehdr __attribute__ ((unused)),
4392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  Elf_Scn *scn __attribute__ ((unused)),
4393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  GElf_Shdr *shdr, Dwarf *dbg)
4394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
4395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\
4396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
4397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_info", (uint64_t) shdr->sh_offset);
4398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If the section is empty we don't have to do anything.  */
4400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_size == 0)
4401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
4402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int maxdies = 20;
4404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
4405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off offset = 0;
4407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* New compilation unit.  */
4409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t cuhl;
4410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  //Dwarf_Half version;
4411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off abbroffset;
4412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  uint8_t addrsize;
4413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  uint8_t offsize;
4414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off nextcu;
4415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project next_cu:
4416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
4417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    &offsize) != 0)
4418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    goto do_return;
4419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
4421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   " Version: %" PRIu16 ", Abbreviation section offset: %"
4422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
4423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
4424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct attrcb_args args;
4427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  args.dwflmod = dwflmod;
4428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  args.dbg = dbg;
4429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  args.addrsize = addrsize;
4430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  args.cu_offset = offset;
4431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  offset += cuhl;
4433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int level = 0;
4435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
4437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
4439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    " in section '%s': %s"),
4440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
4441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      goto do_return;
4442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  do
4445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      offset = dwarf_dieoffset (&dies[level]);
4447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (offset == ~0ul))
4448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("cannot get DIE offset: %s"),
4450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 dwarf_errmsg (-1));
4451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto do_return;
4452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      int tag = dwarf_tag (&dies[level]);
4455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (tag == DW_TAG_invalid))
4456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
4458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				" in section '%s': %s"),
4459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
4460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto do_return;
4461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (" [%6" PRIx64 "]  %*s%s\n",
4464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      (uint64_t) offset, (int) (level * 2), "",
4465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      dwarf_tag_string (tag));
4466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Print the attribute values.  */
4468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      args.level = level;
4469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
4470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Make room for the next level's DIE.  */
4472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (level + 1 == maxdies)
4473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	dies = (Dwarf_Die *) xrealloc (dies,
4474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       (maxdies += 10)
4475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       * sizeof (Dwarf_Die));
4476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      int res = dwarf_child (&dies[level], &dies[level + 1]);
4478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (res > 0)
4479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
4481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (level-- == 0)
4482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      break;
4483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (res == -1))
4485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
4486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      error (0, 0, gettext ("cannot get next DIE: %s\n"),
4487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     dwarf_errmsg (-1));
4488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      goto do_return;
4489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
4490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else if (unlikely (res < 0))
4492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  error (0, 0, gettext ("cannot get next DIE: %s"),
4494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 dwarf_errmsg (-1));
4495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  goto do_return;
4496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
4498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	++level;
4499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (level >= 0);
4501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  offset = nextcu;
4503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (offset != 0)
4504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     goto next_cu;
4505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project do_return:
4507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  free (dies);
4508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
4509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
4512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
4513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  GElf_Ehdr *ehdr __attribute__ ((unused)),
4514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
4515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
4516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\
4517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_line", (uint64_t) shdr->sh_offset);
4519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (shdr->sh_size == 0)
4521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return;
4522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* There is no functionality in libdw to read the information in the
4524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     way it is represented here.  Hardcode the decoder.  */
4525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data = elf_getdata (scn, NULL);
4526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (data == NULL || data->d_buf == NULL))
4527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot get line data section data: %s"),
4529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
4530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
4531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const unsigned char *linep = (const unsigned char *) data->d_buf;
4534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const unsigned char *lineendp;
4535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (linep
4537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
4538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
4539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t start_offset = linep - (const unsigned char *) data->d_buf;
4540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("\nTable at offset %Zu:\n"), start_offset);
4542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
4544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      unsigned int length = 4;
4545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (unit_length == 0xffffffff))
4546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (unlikely (linep + 8 > lineendp))
4548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
4549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    invalid_data:
4550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
4551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     elf_ndxscn (scn), ".debug_line");
4552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      return;
4553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
4554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
4555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  length = 8;
4556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Check whether we have enough room in the section.  */
4559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unit_length < 2 + length + 5 * 1
4560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  || unlikely (linep + unit_length > lineendp))
4561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	goto invalid_data;
4562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      lineendp = linep + unit_length;
4563441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* The next element of the header is the version identifier.  */
4565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
4566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Next comes the header length.  */
4568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Word header_length;
4569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (length == 4)
4570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	header_length = read_4ubyte_unaligned_inc (dbg, linep);
4571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      else
4572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	header_length = read_8ubyte_unaligned_inc (dbg, linep);
4573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      //const unsigned char *header_start = linep;
4574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Next the minimum instruction length.  */
4576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint_fast8_t minimum_instr_len = *linep++;
4577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project        /* Then the flag determining the default value of the is_stmt
4579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   register.  */
4580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint_fast8_t default_is_stmt = *linep++;
4581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Now the line base.  */
4583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      int_fast8_t line_base = *((const int_fast8_t *) linep);
4584441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++linep;
4585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* And the line range.  */
4587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint_fast8_t line_range = *linep++;
4588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* The opcode base.  */
4590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint_fast8_t opcode_base = *linep++;
4591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4592441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Print what we got so far.  */
4593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("\n"
4594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " Length:                     %" PRIu64 "\n"
4595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " DWARF version:              %" PRIuFAST16 "\n"
4596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " Prologue length:            %" PRIu64 "\n"
4597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " Minimum instruction length: %" PRIuFAST8 "\n"
4598441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " Initial value if '%s': %" PRIuFAST8 "\n"
4599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " Line base:                  %" PRIdFAST8 "\n"
4600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " Line range:                 %" PRIuFAST8 "\n"
4601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       " Opcode base:                %" PRIuFAST8 "\n"
4602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       "\n"
4603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		       "Opcodes:\n"),
4604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      (uint64_t) unit_length, version, (uint64_t) header_length,
4605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      minimum_instr_len, "is_stmt", default_is_stmt, line_base,
4606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      line_range, opcode_base);
4607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (linep + opcode_base - 1 >= lineendp))
4609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	invalid_unit:
4611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0,
4612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 gettext ("invalid data at offset %tu in section [%zu] '%s'"),
4613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 linep - (const unsigned char *) data->d_buf,
4614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 elf_ndxscn (scn), ".debug_line");
4615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  linep = lineendp;
4616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  continue;
4617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      int opcode_base_l10 = 1;
4619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      unsigned int tmp = opcode_base;
4620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      while (tmp > 10)
4621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  tmp /= 10;
4623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ++opcode_base_l10;
4624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      const uint8_t *standard_opcode_lengths = linep - 1;
4626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
4627441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
4628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
4629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  (int) linep[cnt - 1]),
4630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		opcode_base_l10, cnt, linep[cnt - 1]);
4631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      linep += opcode_base - 1;
4632441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (linep >= lineendp))
4633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto invalid_unit;
4634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      puts (gettext ("\nDirectory table:"));
4636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      while (*linep != 0)
4637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4638441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
4639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (endp == NULL))
4640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    goto invalid_unit;
4641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (" %s\n", (char *) linep);
4643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  linep = endp + 1;
4645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Skip the final NUL byte.  */
4647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++linep;
4648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (unlikely (linep >= lineendp))
4650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto invalid_unit;
4651441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      puts (gettext ("\nFile name table:\n"
4652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     " Entry Dir   Time      Size      Name"));
4653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (unsigned int cnt = 1; *linep != 0; ++cnt)
4654441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* First comes the file name.  */
4656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  char *fname = (char *) linep;
4657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned char *endp = memchr (fname, '\0', lineendp - linep);
4658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (endp == NULL))
4659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    goto invalid_unit;
4660441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  linep = endp + 1;
4661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Then the index.  */
4663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int diridx;
4664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (diridx, linep);
4665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Next comes the modification time.  */
4667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int mtime;
4668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (mtime, linep);
4669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Finally the length of the file.  */
4671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int fsize;
4672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (fsize, linep);
4673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (" %-5u %-5u %-9u %-9u %s\n",
4675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  cnt, diridx, mtime, fsize, fname);
4676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Skip the final NUL byte.  */
4678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++linep;
4679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      puts (gettext ("\nLine number statements:"));
4681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Word address = 0;
4682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t line = 1;
4683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      uint_fast8_t is_stmt = default_is_stmt;
4684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Default address value, in case we do not find the CU.  */
4686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t address_size
4687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Determine the CU this block is for.  */
4690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Off cuoffset;
4691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Off ncuoffset = 0;
4692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t hsize;
4693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
4694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			   NULL, NULL, NULL) == 0)
4695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Dwarf_Die cudie;
4697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
4698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    continue;
4699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Dwarf_Attribute stmt_list;
4700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
4701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    continue;
4702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  Dwarf_Word lineoff;
4703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
4704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    continue;
4705441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (lineoff == start_offset)
4706441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
4707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Found the CU.  */
4708441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      address_size = cudie.cu->address_size;
4709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      break;
4710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
4711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4713441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      while (linep < lineendp)
4714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
4715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int u128;
4716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  int s128;
4717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Read the opcode.  */
4719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  unsigned int opcode = *linep++;
4720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4721441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Is this a special opcode?  */
4722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (likely (opcode >= opcode_base))
4723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
4724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Yes.  Handling this is quite easy since the opcode value
4725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 is computed with
4726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 opcode = (desired line increment - line_base)
4728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		           + (line_range * address advance) + opcode_base
4729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      */
4730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      int line_increment = (line_base
4731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				    + (opcode - opcode_base) % line_range);
4732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      unsigned int address_increment = (minimum_instr_len
4733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						* ((opcode - opcode_base)
4734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						   / line_range));
4735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Perform the increments.  */
4737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      line += line_increment;
4738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      address += address_increment;
4739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      char *a = format_dwarf_addr (dwflmod, 0, address);
4741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      printf (gettext ("\
4742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng special opcode %u: address+%u = %s, line%+d = %zu\n"),
4743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      opcode, address_increment, a, line_increment, line);
4744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      free (a);
4745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
4746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (opcode == 0)
4747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
4748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* This an extended opcode.  */
4749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (unlikely (linep + 2 > lineendp))
4750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		goto invalid_unit;
4751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The length.  */
4753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      unsigned int len = *linep++;
4754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4755441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (unlikely (linep + len > lineendp))
4756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		goto invalid_unit;
4757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* The sub-opcode.  */
4759441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      opcode = *linep++;
4760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      printf (gettext (" extended opcode %u: "), opcode);
4762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4763441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      switch (opcode)
4764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
4765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNE_end_sequence:
4766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  puts (gettext ("end of sequence"));
4767441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Reset the registers we care about.  */
4769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  address = 0;
4770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  line = 1;
4771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  is_stmt = default_is_stmt;
4772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNE_set_address:
4775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (address_size == 4)
4776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    address = read_4ubyte_unaligned_inc (dbg, linep);
4777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  else
4778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    address = read_8ubyte_unaligned_inc (dbg, linep);
4779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
4780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
4781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    printf (gettext ("set address to %s\n"), a);
4782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    free (a);
4783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
4784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNE_define_file:
4787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  {
4788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    char *fname = (char *) linep;
4789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    unsigned char *endp = memchr (linep, '\0',
4790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project						  lineendp - linep);
4791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    if (unlikely (endp == NULL))
4792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      goto invalid_unit;
4793441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    linep = endp + 1;
4794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    unsigned int diridx;
4796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    get_uleb128 (diridx, linep);
4797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    Dwarf_Word mtime;
4798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    get_uleb128 (mtime, linep);
4799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    Dwarf_Word filelength;
4800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    get_uleb128 (filelength, linep);
4801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    printf (gettext ("\
4803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectdefine new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
4804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    diridx, (uint64_t) mtime, (uint64_t) filelength,
4805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			    fname);
4806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  }
4807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		default:
4810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Unknown, ignore it.  */
4811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  puts (gettext ("unknown opcode"));
4812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  linep += len - 1;
4813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
4815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
4816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if (opcode <= DW_LNS_set_epilogue_begin)
4817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
4818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* This is a known standard opcode.  */
4819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      switch (opcode)
4820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
4821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_copy:
4822441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes no argument.  */
4823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  puts (gettext (" copy"));
4824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_advance_pc:
4827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes one uleb128 parameter which is added to the
4828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     address.  */
4829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  get_uleb128 (u128, linep);
4830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  address += minimum_instr_len * u128;
4831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
4832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
4833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    printf (gettext ("advance address by %u to %s\n"),
4834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    u128, a);
4835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    free (a);
4836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
4837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_advance_line:
4840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes one sleb128 parameter which is added to the
4841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     line.  */
4842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  get_sleb128 (s128, linep);
4843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  line += s128;
4844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  printf (gettext ("\
4845441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project advance line by constant %d to %" PRId64 "\n"),
4846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  s128, (int64_t) line);
4847441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_set_file:
4850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes one uleb128 parameter which is stored in file.  */
4851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  get_uleb128 (u128, linep);
4852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  printf (gettext (" set file to %" PRIu64 "\n"),
4853441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  (uint64_t) u128);
4854441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_set_column:
4857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes one uleb128 parameter which is stored in column.  */
4858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (unlikely (standard_opcode_lengths[opcode] != 1))
4859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    goto invalid_unit;
4860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  get_uleb128 (u128, linep);
4862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  printf (gettext (" set column to %" PRIu64 "\n"),
4863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  (uint64_t) u128);
4864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_negate_stmt:
4867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes no argument.  */
4868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  is_stmt = 1 - is_stmt;
4869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
4870441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  "is_stmt", is_stmt);
4871441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4872441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_set_basic_block:
4874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes no argument.  */
4875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  puts (gettext (" set basic block flag"));
4876441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_const_add_pc:
4879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes no argument.  */
4880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  u128 = (minimum_instr_len
4881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			  * ((255 - opcode_base) / line_range));
4882441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  address += u128;
4883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
4884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
4885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    printf (gettext ("advance address by constant %u to %s\n"),
4886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    u128, a);
4887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    free (a);
4888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
4889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_fixed_advance_pc:
4892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes one 16 bit parameter which is added to the
4893441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		     address.  */
4894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (unlikely (standard_opcode_lengths[opcode] != 1))
4895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    goto invalid_unit;
4896441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4897441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
4898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  address += u128;
4899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
4900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    char *a = format_dwarf_addr (dwflmod, 0, address);
4901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    printf (gettext ("\
4902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengadvance address by fixed value %u to %s\n"),
4903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    u128, a);
4904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    free (a);
4905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
4906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		case DW_LNS_set_prologue_end:
4909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes no argument.  */
4910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  puts (gettext (" set prologue end flag"));
4911441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4912441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		case DW_LNS_set_epilogue_begin:
4914441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  /* Takes no argument.  */
4915441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  puts (gettext (" set epilogue begin flag"));
4916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  break;
4917441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
4918441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
4919441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
4920441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
4921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* This is a new opcode the generator but not we know about.
4922441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 Read the parameters associated with it but then discard
4923441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		 everything.  Read all the parameters for this opcode.  */
4924441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
4925441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				" unknown opcode with %" PRIu8 " parameters:",
4926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				standard_opcode_lengths[opcode]),
4927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      standard_opcode_lengths[opcode]);
4928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
4929441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		{
4930441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  get_uleb128 (u128, linep);
4931441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  if (n != standard_opcode_lengths[opcode])
4932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    putc_unlocked (',', stdout);
4933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  printf (" %u", u128);
4934441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		}
4935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      /* Next round, ignore this opcode.  */
4937441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      continue;
4938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
4939441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
4940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
4941441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* There must only be one data block.  */
4943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  assert (elf_getdata (scn, data) == NULL);
4944441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
4945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
4948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_loc_section (Dwfl_Module *dwflmod,
4949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 Ebl *ebl __attribute__ ((unused)),
4950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 GElf_Ehdr *ehdr __attribute__ ((unused)),
4951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 Elf_Scn *scn __attribute__ ((unused)),
4952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 GElf_Shdr *shdr,
4953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 Dwarf *dbg __attribute__ ((unused)))
4954441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
4955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
4956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (data == NULL))
4958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
4959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("cannot get .debug_loc content: %s"),
4960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     elf_errmsg (-1));
4961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return;
4962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
4963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\
4965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
4966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_loc", (uint64_t) shdr->sh_offset);
4967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
4968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
4969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool first = true;
4971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned char *readp = data->d_buf;
4972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while (readp < (unsigned char *) data->d_buf + data->d_size)
4973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
4974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
4975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (data->d_size - offset < address_size * 2))
4977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext (" [%6tx]  <INVALID DATA>\n"), offset);
4979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
4980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Dwarf_Addr begin;
4983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Dwarf_Addr end;
4984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (address_size == 8)
4985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  begin = read_8ubyte_unaligned_inc (dbg, readp);
4987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  end = read_8ubyte_unaligned_inc (dbg, readp);
4988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
4990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  begin = read_4ubyte_unaligned_inc (dbg, readp);
4992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  end = read_4ubyte_unaligned_inc (dbg, readp);
4993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (begin == (Dwarf_Addr) (uint32_t) -1)
4994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    begin = (Dwarf_Addr) -1l;
4995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
4996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
4997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
4998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
4999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, end);
5000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext (" [%6tx]  base address %s\n"), offset, b);
5001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  free (b);
5002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else if (begin == 0 && end == 0) /* End of list entry.  */
5004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	first = true;
5005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
5006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* We have a location expression entry.  */
5008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
5009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *b = format_dwarf_addr (dwflmod, address_size, begin);
5011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *e = format_dwarf_addr (dwflmod, address_size, end);
5012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (first)		/* First entry in a list.  */
5014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf (gettext (" [%6tx]  %s..%s"), offset, b, e);
5015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
5016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf (gettext ("           %s..%s"), b, e);
5017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  free (b);
5019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  free (e);
5020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
5022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     address_size, len, readp);
5023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  first = false;
5025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  readp += len;
5026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstruct mac_culist
5031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
5032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Die die;
5033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off offset;
5034441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Files *files;
5035441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct mac_culist *next;
5036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project};
5037441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
5040441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmac_compare (const void *p1, const void *p2)
5041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
5042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct mac_culist *m1 = (struct mac_culist *) p1;
5043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct mac_culist *m2 = (struct mac_culist *) p2;
5044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (m1->offset < m2->offset)
5046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return -1;
5047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (m1->offset > m2->offset)
5048441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return 1;
5049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return 0;
5050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
5051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5053441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
5054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     Ebl *ebl __attribute__ ((unused)),
5056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     GElf_Ehdr *ehdr __attribute__ ((unused)),
5057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5058441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
5059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\
5060441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
5061441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_macinfo", (uint64_t) shdr->sh_offset);
5062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  putc_unlocked ('\n', stdout);
5063441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* There is no function in libdw to iterate over the raw content of
5065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     the section but it is easy enough to do.  */
5066441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Elf_Data *data = elf_getdata (scn, NULL);
5067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (data == NULL || data->d_buf == NULL))
5068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot get macro information section data: %s"),
5070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	     elf_errmsg (-1));
5071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
5072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the source file information for all CUs.  */
5075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off offset;
5076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off ncu = 0;
5077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t hsize;
5078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct mac_culist *culist = NULL;
5079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  size_t nculist = 0;
5080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
5081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5082441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Die cudie;
5083441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
5084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	continue;
5085441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5086441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Attribute attr;
5087441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
5088441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	continue;
5089441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5090441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      Dwarf_Word macoff;
5091441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (dwarf_formudata (&attr, &macoff) != 0)
5092441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	continue;
5093441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5094441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
5095441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      newp->die = cudie;
5096441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      newp->offset = macoff;
5097441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      newp->files = NULL;
5098441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      newp->next = culist;
5099441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      culist = newp;
5100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++nculist;
5101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Convert the list into an array for easier consumption.  */
5104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
5105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project							 * sizeof (*cus));
5106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Add sentinel.  */
5107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  cus[nculist].offset = data->d_size;
5108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (nculist > 0)
5109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      for (size_t cnt = nculist - 1; culist != NULL; --cnt)
5111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
5112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  assert (cnt < nculist);
5113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  cus[cnt] = *culist;
5114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  culist = culist->next;
5115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
5116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      /* Sort the array according to the offset in the .debug_macinfo
5118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	 section.  Note we keep the sentinel at the end.  */
5119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      qsort (cus, nculist, sizeof (*cus), mac_compare);
5120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const unsigned char *readp = (const unsigned char *) data->d_buf;
5123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  const unsigned char *readendp = readp + data->d_size;
5124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int level = 1;
5125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (readp < readendp)
5127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      unsigned int opcode = *readp++;
5129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      unsigned int u128;
5130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      unsigned int u128_2;
5131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      const unsigned char *endp;
5132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      switch (opcode)
5134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
5135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_MACINFO_define:
5136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_MACINFO_undef:
5137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_MACINFO_vendor_ext:
5138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /*  For the first two opcodes the parameters are
5139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	        line, string
5140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      For the latter
5141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	        number, string.
5142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      We can treat these cases together.  */
5143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (u128, readp);
5144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  endp = memchr (readp, '\0', readendp - readp);
5146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (endp == NULL))
5147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
5148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      printf (gettext ("\
5149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project%*s*** non-terminated string at end of section"),
5150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		      level, "");
5151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      return;
5152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
5153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (opcode == DW_MACINFO_define)
5155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf ("%*s#define %s, line %u\n",
5156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    level, "", (char *) readp, u128);
5157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else if (opcode == DW_MACINFO_undef)
5158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf ("%*s#undef %s, line %u\n",
5159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		    level, "", (char *) readp, u128);
5160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  else
5161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
5162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  readp = endp + 1;
5164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
5165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_MACINFO_start_file:
5167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* The two parameters are line and file index, in this order.  */
5168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (u128, readp);
5169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  get_uleb128 (u128_2, readp);
5170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Find the CU DIE for this file.  */
5172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t macoff = readp - (const unsigned char *) data->d_buf;
5173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  const char *fname = "???";
5174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  if (macoff >= cus[0].offset)
5175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
5176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      while (macoff >= cus[1].offset)
5177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		++cus;
5178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (cus[0].files == NULL
5180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		&& dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
5181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		cus[0].files = (Dwarf_Files *) -1l;
5182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      if (cus[0].files != (Dwarf_Files *) -1l)
5184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
5185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 ?: "???");
5186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
5187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf ("%*sstart_file %u, [%u] %s\n",
5189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  level, "", u128, u128_2, fname);
5190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ++level;
5191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
5192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	case DW_MACINFO_end_file:
5194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  --level;
5195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf ("%*send_file\n", level, "");
5196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* Nothing more to do.  */
5197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
5198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	default:
5200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  // XXX gcc seems to generate files with a trailing zero.
5201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (opcode != 0 || readp != readendp))
5202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
5203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
5204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
5205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
5207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Callback for printing global names.  */
5210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int
5211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
5212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		void *arg)
5213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
5214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int *np = (int *) arg;
5215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext (" [%5d] DIE offset: %6" PRId64
5217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
5218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  (*np)++, global->die_offset, global->cu_offset, global->name);
5219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return 0;
5221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
5222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
5225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
5226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      Ebl *ebl __attribute__ ((unused)),
5228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      GElf_Ehdr *ehdr __attribute__ ((unused)),
5229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      Elf_Scn *scn __attribute__ ((unused)),
5230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			      GElf_Shdr *shdr, Dwarf *dbg)
5231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
5232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
5233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_pubnames", (uint64_t) shdr->sh_offset);
5234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int n = 0;
5236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
5237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
5238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the content of the DWARF string section '.debug_str'.  */
5240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
5241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 Ebl *ebl __attribute__ ((unused)),
5243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 GElf_Ehdr *ehdr __attribute__ ((unused)),
5244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 Elf_Scn *scn __attribute__ ((unused)),
5245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project			 GElf_Shdr *shdr, Dwarf *dbg)
5246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
5247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Compute floor(log16(shdr->sh_size)).  */
5248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  GElf_Addr tmp = shdr->sh_size;
5249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int digits = 1;
5250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (tmp >= 16)
5251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      ++digits;
5253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      tmp >>= 4;
5254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  digits = MAX (4, digits);
5256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
5258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		   " %*s  String\n"),
5259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  ".debug_str", (uint64_t) shdr->sh_offset,
5260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  /* TRANS: the debugstr| prefix makes the string unique.  */
5261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  digits + 2, sgettext ("debugstr|Offset"));
5262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  Dwarf_Off offset = 0;
5264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while (offset < shdr->sh_size)
5265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      size_t len;
5267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      const char *str = dwarf_getstring (dbg, offset, &len);
5268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (str == NULL))
5269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
5270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  printf (gettext (" *** error while reading strings: %s\n"),
5271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  dwarf_errmsg (-1));
5272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  break;
5273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
5274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
5276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      offset += len + 1;
5278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
5280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
5282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
5283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
5284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Before we start the real work get a debug context descriptor.  */
5285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Dwarf_Addr dwbias;
5286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
5287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (dbg == NULL)
5288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      error (0, 0, gettext ("cannot get debug context descriptor: %s"),
5290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     dwfl_errmsg (-1));
5291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return;
5292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* Get the section header string table index.  */
5295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
5296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
5297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    error (EXIT_FAILURE, 0,
5298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	   gettext ("cannot get section header string table index"));
5299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Look through all the sections for the debugging sections to print.  */
5301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *scn = NULL;
5302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
5303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
5304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr shdr_mem;
5305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
5306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
5308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
5309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  static const struct
5310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  {
5311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    const char *name;
5312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    enum section_e bitmask;
5313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    void (*fp) (Dwfl_Module *, Ebl *,
5314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
5315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  } debug_sections[] =
5316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
5317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define NEW_SECTION(name) \
5318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      { ".debug_" #name, section_##name, print_debug_##name##_section }
5319441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (abbrev),
5320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (aranges),
5321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (frame),
5322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (info),
5323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (line),
5324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (loc),
5325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (pubnames),
5326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (str),
5327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      NEW_SECTION (macinfo),
5328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      NEW_SECTION (ranges),
5329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      { ".eh_frame", section_frame, print_debug_frame_section }
5330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    };
5331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  const int ndebug_sections = (sizeof (debug_sections)
5332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project				       / sizeof (debug_sections[0]));
5333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  const char *name = elf_strptr (ebl->elf, shstrndx,
5334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project					 shdr->sh_name);
5335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  int n;
5336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	  for (n = 0; n < ndebug_sections; ++n)
5338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    if (strcmp (name, debug_sections[n].name) == 0)
5339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      {
5340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		if (print_debug_sections & debug_sections[n].bitmask)
5341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
5342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		break;
5343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      }
5344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
5345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
5346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define ITEM_INDENT		4
5350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define ITEM_WRAP_COLUMN	150
5351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define REGISTER_WRAP_COLUMN	75
5352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
5354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   make the line exceed ITEM_WRAP_COLUMN.  Unpadded numbers look better
5355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   for the core items.  But we do not want the line breaks to depend on
5356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   the particular values.  */
5357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int
5358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__attribute__ ((format (printf, 7, 8)))
5359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_core_item (unsigned int colno, char sep, unsigned int wrap,
5360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 size_t name_width, const char *name,
5361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 size_t format_max, const char *format, ...)
5362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t len = strlen (name);
5364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (name_width < len)
5365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    name_width = len;
5366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t n = name_width + sizeof ": " - 1 + format_max;
5368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (colno == 0)
5370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf ("%*s", ITEM_INDENT, "");
5372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno = ITEM_INDENT + n;
5373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else if (colno + 2 + n < wrap)
5375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf ("%c ", sep);
5377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno += 2 + n;
5378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
5380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf ("\n%*s", ITEM_INDENT, "");
5382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno = ITEM_INDENT + n;
5383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  printf ("%s: %*s", name, (int) (name_width - len), "");
5386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  va_list ap;
5388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  va_start (ap, format);
5389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  vprintf (format, ap);
5390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  va_end (ap);
5391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return colno;
5393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const void *
5396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconvert (Elf *core, Elf_Type type, uint_fast16_t count,
5397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 void *value, const void *data, size_t size)
5398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data valuedata =
5400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_type = type,
5402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_buf = value,
5403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
5404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_version = EV_CURRENT,
5405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
5406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data indata =
5407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_type = type,
5409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_buf = (void *) data,
5410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_size = valuedata.d_size,
5411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      .d_version = EV_CURRENT,
5412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    };
5413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
5415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 ? elf32_xlatetom : elf64_xlatetom)
5416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
5417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (d == NULL)
5418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0,
5419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
5420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return data + indata.d_size;
5422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengtypedef uint8_t GElf_Byte;
5425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int
5427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
5428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  unsigned int colno, size_t *repeated_size)
5429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast16_t count = item->count ?: 1;
5431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define TYPES								      \
5433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4);			      \
5434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6);			      \
5435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11);			      \
5436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11);			      \
5437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20);		      \
5438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
5439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
5441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  union { TYPES; } value;
5442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE
5443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  void *data = &value;
5445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
5446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t convsize = size;
5447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (repeated_size != NULL)
5448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
5450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  data = alloca (*repeated_size);
5452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  count *= *repeated_size / size;
5453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  convsize = count * size;
5454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  *repeated_size -= convsize;
5455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
5457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	*repeated_size -= size;
5458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  desc = convert (core, item->type, count, data, desc + item->offset, convsize);
5461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Type type = item->type;
5463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (type == ELF_T_ADDR)
5464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
5465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  switch (item->format)
5467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'd':
5469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (count == 1);
5470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      switch (type)
5471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name, hex, dec, max)				      \
5473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case ELF_T_##NAME:						      \
5474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
5475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     0, item->name, max, dec, value.Name[0]); \
5476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break
5477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  TYPES;
5478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE
5479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	default:
5480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  abort ();
5481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
5483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'x':
5485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (count == 1);
5486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      switch (type)
5487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name, hex, dec, max)				      \
5489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case ELF_T_##NAME:						      \
5490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN,	      \
5491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     0, item->name, max, hex, value.Name[0]); \
5492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break
5493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  TYPES;
5494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE
5495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	default:
5496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  abort ();
5497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
5499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'b':
5501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'B':
5502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (size % sizeof (unsigned int) == 0);
5503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      unsigned int nbits = count * size * 8;
5504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      unsigned int pop = 0;
5505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
5506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	pop += __builtin_popcount (*i);
5507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bool negate = pop > nbits / 2;
5508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const unsigned int bias = item->format == 'b';
5509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
5511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	char printed[(negate ? nbits - pop : pop) * 16];
5512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	char *p = printed;
5513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	*p = '\0';
5514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
5516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
5517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    assert (size == sizeof (unsigned int) * 2);
5518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    for (unsigned int *i = data;
5519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 (void *) i < data + count * size; i += 2)
5520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
5521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		unsigned int w = i[1];
5522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		i[1] = i[0];
5523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		i[0] = w;
5524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
5525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
5526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	unsigned int lastbit = 0;
5528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	for (const unsigned int *i = data;
5529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     (void *) i < data + count * size; ++i)
5530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
5531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    unsigned int bit = ((void *) i - data) * 8;
5532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    unsigned int w = negate ? ~*i : *i;
5533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    while (w != 0)
5534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
5535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		int n = ffs (w);
5536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		w >>= n;
5537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		bit += n;
5538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (lastbit + 1 != bit)
5540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
5541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		else if (lastbit == 0)
5542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  p += sprintf (p, "%u", bit - bias);
5543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		lastbit = bit;
5545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
5546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
5547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (lastbit > 0 && lastbit + 1 != nbits)
5548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  p += sprintf (p, "-%u", nbits - bias);
5549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				 4 + nbits * 4,
5552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				 negate ? "~<%s>" : "<%s>", printed);
5553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
5554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
5555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'T':
5557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case (char) ('T'|0x80):
5558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (count == 2);
5559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Dwarf_Word sec;
5560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Dwarf_Word usec;
5561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t maxfmt = 7;
5562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      switch (type)
5563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name, hex, dec, max)				      \
5565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case ELF_T_##NAME:						      \
5566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    sec = value.Name[0];					      \
5567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    usec = value.Name[1];					      \
5568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    maxfmt += max;						      \
5569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break
5570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  TYPES;
5571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE
5572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	default:
5573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  abort ();
5574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (item->format == (char) ('T'|0x80)))
5576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* This is a hack for an ill-considered 64-bit ABI where
5578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     tv_usec is actually a 32-bit field with 32 bits of padding
5579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     rounding out struct timeval.  We've already converted it as
5580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     a 64-bit field.  For little-endian, this just means the
5581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     high half is the padding; it's presumably zero, but should
5582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     be ignored anyway.  For big-endian, it means the 32-bit
5583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     field went into the high half of USEC.  */
5584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Ehdr ehdr_mem;
5585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
5586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
5587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    usec >>= 32;
5588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
5589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    usec &= UINT32_MAX;
5590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
5593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
5594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'c':
5596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (count == 1);
5597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       1, "%c", value.Byte[0]);
5599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
5600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 's':
5602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
5603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       count, "%.*s", (int) count, value.Byte);
5604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
5605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    default:
5607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, "XXX not handling format '%c' for %s",
5608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     item->format, item->name);
5609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
5610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef TYPES
5613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return colno;
5615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Sort items by group, and by layout offset within each group.  */
5619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
5620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_core_items (const void *a, const void *b)
5621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *const *p1 = a;
5623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *const *p2 = b;
5624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *item1 = *p1;
5625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *item2 = *p2;
5626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return ((item1->group == item2->group ? 0
5628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   : strcmp (item1->group, item2->group))
5629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ?: (int) item1->offset - (int) item2->offset);
5630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Sort item groups by layout offset of the first item in the group.  */
5633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
5634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_core_item_groups (const void *a, const void *b)
5635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *const *const *p1 = a;
5637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *const *const *p2 = b;
5638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *const *group1 = *p1;
5639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *const *group2 = *p2;
5640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *item1 = *group1;
5641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *item2 = *group2;
5642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return (int) item1->offset - (int) item2->offset;
5644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int
5647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_core_items (Elf *core, const void *desc, size_t descsz,
5648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   const Ebl_Core_Item *items, size_t nitems)
5649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (nitems == 0)
5651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return 0;
5652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Sort to collect the groups together.  */
5654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *sorted_items[nitems];
5655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t i = 0; i < nitems; ++i)
5656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    sorted_items[i] = &items[i];
5657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
5658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Collect the unique groups and sort them.  */
5660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item **groups[nitems];
5661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  groups[0] = &sorted_items[0];
5662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t ngroups = 1;
5663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t i = 1; i < nitems; ++i)
5664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    if (sorted_items[i]->group != sorted_items[i - 1]->group
5665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
5666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      groups[ngroups++] = &sorted_items[i];
5667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
5668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Write out all the groups.  */
5670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int colno = 0;
5671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const void *last = desc;
5673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (nitems == 1)
5674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t size = descsz;
5676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno = handle_core_item (core, sorted_items[0], desc, colno, &size);
5677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (size == 0)
5678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return colno;
5679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      desc += descsz - size;
5680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      descsz = size;
5681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  do
5684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (size_t i = 0; i < ngroups; ++i)
5686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  for (const Ebl_Core_Item **item = groups[i];
5688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       (item < &sorted_items[nitems]
5689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		&& ((*item)->group == groups[i][0]->group
5690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    || !strcmp ((*item)->group, groups[i][0]->group)));
5691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       ++item)
5692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    colno = handle_core_item (core, *item, desc, colno, NULL);
5693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Force a line break at the end of the group.  */
5695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  colno = ITEM_WRAP_COLUMN;
5696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (descsz == 0)
5699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	break;
5700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* This set of items consumed a certain amount of the note's data.
5702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 If there is more data there, we have another unit of the same size.
5703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 Loop to print that out too.  */
5704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const Ebl_Core_Item *item = &items[nitems - 1];
5705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t eltsz = item->offset + gelf_fsize (core, item->type,
5706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						item->count ?: 1, EV_CURRENT);
5707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int reps = -1;
5709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      do
5710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ++reps;
5712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  desc += eltsz;
5713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  descsz -= eltsz;
5714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while (descsz >= eltsz && !memcmp (desc, last, eltsz));
5716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (reps == 1)
5718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* For just one repeat, print it unabridged twice.  */
5720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  desc -= eltsz;
5721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  descsz += eltsz;
5722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else if (reps > 1)
5724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	printf (gettext ("\n%*s... <repeats %u more times> ..."),
5725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		ITEM_INDENT, "", reps);
5726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      last = desc;
5728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while (descsz > 0);
5730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return colno;
5732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int
5735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
5736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      unsigned int colno)
5737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  desc += regloc->offset;
5739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  abort ();			/* XXX */
5741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return colno;
5742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
5743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int
5746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_core_register (Ebl *ebl, Elf *core, int maxregname,
5747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      const Ebl_Register_Location *regloc, const void *desc,
5748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      unsigned int colno)
5749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (regloc->bits % 8 != 0)
5751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return handle_bit_registers (regloc, desc, colno);
5752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  desc += regloc->offset;
5754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
5756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *pfx;
5758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *set;
5759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char name[16];
5760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int bits;
5761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int type;
5762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ssize_t n = ebl_register_info (ebl, reg, name, sizeof name,
5763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     &pfx, &set, &bits, &type);
5764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (n <= 0)
5765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, 0,
5766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       gettext ("unable to handle register number %d"),
5767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       regloc->regno);
5768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define TYPES								      \
5770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4);			      \
5771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6);			      \
5772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11);		      \
5773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64, 20)
5774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define BITS(bits, xtype, sfmt, ufmt, max)				\
5776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint##bits##_t b##bits; int##bits##_t b##bits##s
5777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      union { TYPES; uint64_t b128[2]; } value;
5778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef	BITS
5779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      switch (type)
5781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_ATE_unsigned:
5783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_ATE_signed:
5784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case DW_ATE_address:
5785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  switch (bits)
5786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
5787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define BITS(bits, xtype, sfmt, ufmt, max)				      \
5788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    case bits:							      \
5789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
5790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (type == DW_ATE_signed)				      \
5791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
5792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 maxregname, name,		      \
5793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 max, sfmt, value.b##bits##s);	      \
5794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else							      \
5795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,    \
5796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 maxregname, name,		      \
5797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 max, ufmt, value.b##bits);	      \
5798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break
5799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    TYPES;
5801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    case 128:
5803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      assert (type == DW_ATE_unsigned);
5804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
5805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
5806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
5807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       maxregname, name,
5808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       34, "0x%.16" PRIx64 "%.16" PRIx64,
5809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       value.b128[!be], value.b128[be]);
5810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break;
5811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    default:
5813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      abort ();
5814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef	BITS
5815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
5816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
5817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	default:
5819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Print each byte in hex, the whole thing in native byte order.  */
5820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  assert (bits % 8 == 0);
5821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  const uint8_t *bytes = desc;
5822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  desc += bits / 8;
5823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char hex[bits / 4 + 1];
5824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  hex[bits / 4] = '\0';
5825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int incr = 1;
5826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
5827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
5828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      bytes += bits / 8 - 1;
5829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      incr = -1;
5830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
5831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t idx = 0;
5832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
5833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
5834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
5835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
5836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
5837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
5838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				   maxregname, name,
5839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				   2 + sizeof hex - 1, "0x%s", hex);
5840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
5841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      desc += regloc->pad;
5843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef TYPES
5845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return colno;
5848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct register_info
5852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Register_Location *regloc;
5854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *set;
5855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char name[16];
5856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Dwarf_Half regno;
5857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint8_t bits;
5858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint8_t type;
5859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng};
5860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
5862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengregister_bitpos (const struct register_info *r)
5863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return (r->regloc->offset * 8
5865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  + ((r->regno - r->regloc->regno)
5866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     * (r->regloc->bits + r->regloc->pad * 8)));
5867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
5870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_sets_by_info (const struct register_info *r1,
5871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      const struct register_info *r2)
5872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return ((int) r2->bits - (int) r1->bits
5874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ?: register_bitpos (r1) - register_bitpos (r2));
5875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Sort registers by set, and by size and layout offset within each set.  */
5878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
5879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_registers (const void *a, const void *b)
5880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const struct register_info *r1 = a;
5882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const struct register_info *r2 = b;
5883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Unused elements sort last.  */
5885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (r1->regloc == NULL)
5886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return r2->regloc == NULL ? 0 : 1;
5887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (r2->regloc == NULL)
5888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
5889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
5891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ?: compare_sets_by_info (r1, r2));
5892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Sort register sets by layout offset of the first register in the set.  */
5895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
5896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_register_sets (const void *a, const void *b)
5897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const struct register_info *const *p1 = a;
5899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const struct register_info *const *p2 = b;
5900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return compare_sets_by_info (*p1, *p2);
5901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int
5904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_core_registers (Ebl *ebl, Elf *core, const void *desc,
5905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       const Ebl_Register_Location *reglocs, size_t nregloc)
5906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (nregloc == 0)
5908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return 0;
5909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
5911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (maxnreg <= 0)
5912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0,
5913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   gettext ("cannot register info: %s"), elf_errmsg (-1));
5914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct register_info regs[maxnreg];
5916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  memset (regs, 0, sizeof regs);
5917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Sort to collect the sets together.  */
5919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int maxreg = 0;
5920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t i = 0; i < nregloc; ++i)
5921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    for (int reg = reglocs[i].regno;
5922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 reg < reglocs[i].regno + reglocs[i].count;
5923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 ++reg)
5924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
5925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	assert (reg < maxnreg);
5926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (reg > maxreg)
5927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  maxreg = reg;
5928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	struct register_info *info = &regs[reg];
5929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	const char *pfx;
5931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	int bits;
5932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	int type;
5933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	ssize_t n = ebl_register_info (ebl, reg, info->name, sizeof info->name,
5934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				       &pfx, &info->set, &bits, &type);
5935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (n <= 0)
5936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (EXIT_FAILURE, 0,
5937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 gettext ("cannot register info: %s"), elf_errmsg (-1));
5938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	info->regloc = &reglocs[i];
5940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	info->regno = reg;
5941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	info->bits = bits;
5942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	info->type = type;
5943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
5944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
5945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Collect the unique sets and sort them.  */
5947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  inline bool same_set (const struct register_info *a,
5948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			const struct register_info *b)
5949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  {
5950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (a < &regs[maxnreg] && a->regloc != NULL
5951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    && b < &regs[maxnreg] && b->regloc != NULL
5952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    && a->bits == b->bits
5953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    && (a->set == b->set || !strcmp (a->set, b->set)));
5954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  }
5955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct register_info *sets[maxreg + 1];
5956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  sets[0] = &regs[0];
5957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t nsets = 1;
5958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int i = 1; i <= maxreg; ++i)
5959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
5960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      sets[nsets++] = &regs[i];
5961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
5962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Write out all the sets.  */
5964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int colno = 0;
5965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t i = 0; i < nsets; ++i)
5966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
5967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Find the longest name of a register in this set.  */
5968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t maxname = 0;
5969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const struct register_info *end;
5970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (end = sets[i]; same_set (sets[i], end); ++end)
5971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
5972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t len = strlen (end->name);
5973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (len > maxname)
5974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    maxname = len;
5975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
5976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (const struct register_info *reg = sets[i];
5978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   reg < end;
5979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   reg += reg->regloc->count ?: 1)
5980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	colno = handle_core_register (ebl, core, maxname,
5981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      reg->regloc, desc, colno);
5982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Force a line break at the end of the group.  */
5984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      colno = REGISTER_WRAP_COLUMN;
5985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
5986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return colno;
5988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
5989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
5991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
5992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
5993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
5994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (data == NULL)
5995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  elf_error:
5996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0,
5997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
5998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
6000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t i = 0; i < nauxv; ++i)
6001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_auxv_t av_mem;
6003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
6004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (av == NULL)
6005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto elf_error;
6006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *name;
6008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *fmt;
6009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
6010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Unknown type.  */
6012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (av->a_un.a_val == 0)
6013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("    %" PRIu64 "\n", av->a_type);
6014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
6015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
6016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    av->a_type, av->a_un.a_val);
6017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
6018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
6019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	switch (fmt[0])
6020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
6021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case '\0':		/* Normally zero.  */
6022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (av->a_un.a_val == 0)
6023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
6024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		printf ("    %s\n", name);
6025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		break;
6026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
6027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* Fall through */
6028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case 'x':		/* hex */
6029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case 'p':		/* address */
6030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case 's':		/* address of string */
6031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
6032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
6033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case 'u':
6034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
6035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
6036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case 'd':
6037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
6038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
6039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  case 'b':
6041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
6042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    GElf_Xword bit = 1;
6043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    const char *pfx = "<";
6044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
6045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      {
6046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (av->a_un.a_val & bit)
6047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  {
6048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    printf ("%s%s", pfx, p);
6049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    pfx = " ";
6050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  }
6051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		bit <<= 1;
6052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      }
6053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf (">\n");
6054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    break;
6055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  default:
6057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    abort ();
6058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
6059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc)
6064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Word regs_offset;
6066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t nregloc;
6067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Register_Location *reglocs;
6068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t nitems;
6069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Ebl_Core_Item *items;
6070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (! ebl_core_note (ebl, nhdr->n_type, nhdr->n_descsz,
6072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
6073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return;
6074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Pass 0 for DESCSZ when there are registers in the note,
6076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     so that the ITEMS array does not describe the whole thing.
6077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     For non-register notes, the actual descsz might be a multiple
6078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     of the unit size, not just exactly the unit size.  */
6079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int colno = handle_core_items (ebl->elf, desc,
6080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					  nregloc == 0 ? nhdr->n_descsz : 0,
6081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					  items, nitems);
6082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (colno != 0)
6083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    putchar_unlocked ('\n');
6084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
6086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				 reglocs, nregloc);
6087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (colno != 0)
6088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    putchar_unlocked ('\n');
6089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
6093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   GElf_Off start, Elf_Data *data)
6094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
6096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (data == NULL)
6098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    goto bad_note;
6099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t offset = 0;
6101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Nhdr nhdr;
6102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t name_offset;
6103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t desc_offset;
6104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while (offset < data->d_size
6105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 && (offset = gelf_getnote (data, offset,
6106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				    &nhdr, &name_offset, &desc_offset)) > 0)
6107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *name = data->d_buf + name_offset;
6109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *desc = data->d_buf + desc_offset;
6110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char buf[100];
6112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char buf2[100];
6113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
6114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      (int) nhdr.n_namesz, name, nhdr.n_descsz,
6115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ehdr->e_type == ET_CORE
6116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
6117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 buf, sizeof (buf))
6118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      : ebl_object_note_type_name (ebl, nhdr.n_type,
6119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					   buf2, sizeof (buf2)));
6120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Filter out invalid entries.  */
6122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (memchr (name, '\0', nhdr.n_namesz) != NULL
6123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* XXX For now help broken Linux kernels.  */
6124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || 1)
6125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (ehdr->e_type == ET_CORE)
6127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
6128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (nhdr.n_type == NT_AUXV)
6129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
6130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				  start + desc_offset);
6131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
6132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		handle_core_note (ebl, &nhdr, desc);
6133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
6134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
6135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
6136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
6137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (offset == data->d_size)
6140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return;
6141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bad_note:
6143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  error (EXIT_FAILURE, 0,
6144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 gettext ("cannot get content of note section: %s"),
6145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 elf_errmsg (-1));
6146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
6149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projecthandle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
6150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
6151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* If we have section headers, just look for SHT_NOTE sections.
6152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     In a debuginfo file, the program headers are not reliable.  */
6153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (shnum != 0)
6154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Get the section header string table index.  */
6156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t shstrndx;
6157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
6158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, 0,
6159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       gettext ("cannot get section header string table index"));
6160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Scn *scn = NULL;
6162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
6163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr shdr_mem;
6165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
6166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
6168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* Not what we are looking for.  */
6169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    continue;
6170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext ("\
6172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
6173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  elf_ndxscn (scn),
6174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
6175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  shdr->sh_size, shdr->sh_offset);
6176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
6178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     elf_getdata (scn, NULL));
6179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
6180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return;
6181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* We have to look through the program header to find the note
6184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     sections.  There can be more than one.  */
6185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
6186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
6187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Phdr mem;
6188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
6189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      if (phdr == NULL || phdr->p_type != PT_NOTE)
6191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	/* Not what we are looking for.  */
6192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	continue;
6193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      printf (gettext ("\
6195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
6196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	      phdr->p_filesz, phdr->p_offset);
6197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      handle_notes_data (ebl, ehdr, phdr->p_offset,
6199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 elf_getdata_rawchunk (ebl->elf,
6200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					       phdr->p_offset, phdr->p_filesz,
6201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					       ELF_T_NHDR));
6202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghex_dump (const uint8_t *data, size_t len)
6208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t pos = 0;
6210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while (pos < len)
6211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf ("  0x%08Zx ", pos);
6213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const size_t chunk = MIN (len - pos, 16);
6215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (size_t i = 0; i < chunk; ++i)
6217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (i % 4 == 3)
6218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%02x ", data[pos + i]);
6219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	else
6220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%02x", data[pos + i]);
6221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (chunk < 16)
6223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
6224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (size_t i = 0; i < chunk; ++i)
6226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	{
6227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unsigned char b = data[pos + i];
6228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("%c", isprint (b) ? b : '.');
6229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
6230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      putchar ('\n');
6232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      pos += chunk;
6233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
6238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
6240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"),
6241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    elf_ndxscn (scn), name);
6242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
6243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Data *data = elf_rawdata (scn, NULL);
6245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (data == NULL)
6246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
6247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       elf_ndxscn (scn), name, elf_errmsg (-1));
6248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
6249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64
6251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   " bytes at offset %#0" PRIx64 ":\n"),
6252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  elf_ndxscn (scn), name,
6253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  shdr->sh_size, shdr->sh_offset);
6254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  hex_dump (data->d_buf, data->d_size);
6255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
6256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
6261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (shdr->sh_size == 0)
6263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    printf (gettext ("\nSection [%Zu] '%s' is empty.\n"),
6264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    elf_ndxscn (scn), name);
6265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Data *data = elf_rawdata (scn, NULL);
6267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (data == NULL)
6268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"),
6269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   elf_ndxscn (scn), name, elf_errmsg (-1));
6270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
6271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64
6273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       " bytes at offset %#0" PRIx64 ":\n"),
6274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      elf_ndxscn (scn), name,
6275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      shdr->sh_size, shdr->sh_offset);
6276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *start = data->d_buf;
6278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *const limit = start + data->d_size;
6279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      do
6280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  const char *end = memchr (start, '\0', limit - start);
6282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  const size_t pos = start - (const char *) data->d_buf;
6283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (end == NULL))
6284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    {
6285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      printf ("  [%6Zx]- %.*s\n",
6286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      pos, (int) (limit - start), start);
6287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      break;
6288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
6289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf ("  [%6Zx]  %s\n", pos, start);
6290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  start = end + 1;
6291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	} while (start < limit);
6292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengfor_each_section_argument (Elf *elf, const struct section_argument *list,
6297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
6298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					 const char *name))
6299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Get the section header string table index.  */
6301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
6302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (elf_getshstrndx (elf, &shstrndx) < 0)
6303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0,
6304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   gettext ("cannot get section header string table index"));
6305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (const struct section_argument *a = list; a != NULL; a = a->next)
6307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Scn *scn;
6309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      GElf_Shdr shdr_mem;
6310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      const char *name = NULL;
6311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *endp = NULL;
6313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      unsigned long int shndx = strtoul (a->arg, &endp, 0);
6314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (endp != a->arg && *endp == '\0')
6315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  scn = elf_getscn (elf, shndx);
6317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (scn == NULL)
6318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
6319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx);
6320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      continue;
6321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
6322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
6324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
6325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   elf_errmsg (-1));
6326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
6327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
6328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
6329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Need to look up the section by name.  */
6331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  scn = NULL;
6332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  while ((scn = elf_nextscn (elf, scn)) != NULL)
6333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
6334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
6335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		continue;
6336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
6337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (name == NULL)
6338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		continue;
6339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (!strcmp (name, a->arg))
6340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		break;
6341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	    }
6342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (scn == NULL))
6344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
6345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg);
6346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      continue;
6347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
6348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
6349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      (*dump) (scn, &shdr_mem, name);
6351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdump_data (Ebl *ebl)
6356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
6358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdump_strings (Ebl *ebl)
6362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for_each_section_argument (ebl->elf, string_sections, &print_string_section);
6364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_strings (Ebl *ebl)
6368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Get the section header string table index.  */
6370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t shstrndx;
6371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
6372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0,
6373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   gettext ("cannot get section header string table index"));
6374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Scn *scn;
6376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  GElf_Shdr shdr_mem;
6377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *name;
6378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  scn = NULL;
6379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
6380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (gelf_getshdr (scn, &shdr_mem) == NULL)
6382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	continue;
6383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (shdr_mem.sh_type != SHT_PROGBITS
6385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || !(shdr_mem.sh_flags & SHF_STRINGS))
6386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	continue;
6387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
6389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (name == NULL)
6390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	continue;
6391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      print_string_section (scn, &shdr_mem, name);
6393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
6395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
6397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdump_archive_index (Elf *elf, const char *fname)
6398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
6399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t narsym;
6400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
6401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (arsym == NULL)
6402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int result = elf_errno ();
6404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (result != ELF_E_NO_INDEX))
6405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, 0,
6406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       gettext ("cannot get symbol index of archive '%s': %s"),
6407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       fname, elf_errmsg (result));
6408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
6409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	printf (gettext ("\nArchive '%s' has no symbol index\n"), fname);
6410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return;
6411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
6412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"),
6414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  fname, narsym);
6415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t as_off = 0;
6417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
6418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
6419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (s->as_off != as_off)
6420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
6421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  as_off = s->as_off;
6422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf *subelf;
6424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (elf_rand (elf, as_off) == 0)
6425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
6426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   == NULL))
6427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
6428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    while (1)
6429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
6430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (EXIT_FAILURE, 0,
6431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     gettext ("cannot extract member at offset %Zu in '%s': %s"),
6432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     as_off, fname, elf_errmsg (-1));
6433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  const Elf_Arhdr *h = elf_getarhdr (subelf);
6435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  printf (gettext ("Archive member '%s' contains:\n"), h->ar_name);
6437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  elf_end (subelf);
6439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project	}
6440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
6441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf ("\t%s\n", s->as_name);
6442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
6443441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
6444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "debugpred.h"
6446