xref: /aosp_15_r20/external/elfutils/src/readelf.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Print information from ELF file in human-readable form.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 1999-2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2023 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of the GNU General Public License as published by
8*7304104dSAndroid Build Coastguard Worker    the Free Software Foundation; either version 3 of the License, or
9*7304104dSAndroid Build Coastguard Worker    (at your option) any later version.
10*7304104dSAndroid Build Coastguard Worker 
11*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
12*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
13*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*7304104dSAndroid Build Coastguard Worker    GNU General Public License for more details.
15*7304104dSAndroid Build Coastguard Worker 
16*7304104dSAndroid Build Coastguard Worker    You should have received a copy of the GNU General Public License
17*7304104dSAndroid Build Coastguard Worker    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
20*7304104dSAndroid Build Coastguard Worker # include <config.h>
21*7304104dSAndroid Build Coastguard Worker #endif
22*7304104dSAndroid Build Coastguard Worker 
23*7304104dSAndroid Build Coastguard Worker #include <argp.h>
24*7304104dSAndroid Build Coastguard Worker #include <assert.h>
25*7304104dSAndroid Build Coastguard Worker #include <ctype.h>
26*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
27*7304104dSAndroid Build Coastguard Worker #include <errno.h>
28*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
29*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
30*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
31*7304104dSAndroid Build Coastguard Worker #include <langinfo.h>
32*7304104dSAndroid Build Coastguard Worker #include <libdw.h>
33*7304104dSAndroid Build Coastguard Worker #include <libdwfl.h>
34*7304104dSAndroid Build Coastguard Worker #include <locale.h>
35*7304104dSAndroid Build Coastguard Worker #include <stdarg.h>
36*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
37*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
38*7304104dSAndroid Build Coastguard Worker #include <stdio_ext.h>
39*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
40*7304104dSAndroid Build Coastguard Worker #include <string.h>
41*7304104dSAndroid Build Coastguard Worker #include <strings.h>
42*7304104dSAndroid Build Coastguard Worker #include <time.h>
43*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
44*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
45*7304104dSAndroid Build Coastguard Worker #include <signal.h>
46*7304104dSAndroid Build Coastguard Worker 
47*7304104dSAndroid Build Coastguard Worker #include <libeu.h>
48*7304104dSAndroid Build Coastguard Worker #include <system.h>
49*7304104dSAndroid Build Coastguard Worker #include <printversion.h>
50*7304104dSAndroid Build Coastguard Worker #include "../libelf/libelfP.h"
51*7304104dSAndroid Build Coastguard Worker #include "../libelf/common.h"
52*7304104dSAndroid Build Coastguard Worker #include "../libebl/libeblP.h"
53*7304104dSAndroid Build Coastguard Worker #include "../libdwelf/libdwelf.h"
54*7304104dSAndroid Build Coastguard Worker #include "../libdw/libdwP.h"
55*7304104dSAndroid Build Coastguard Worker #include "../libdwfl/libdwflP.h"
56*7304104dSAndroid Build Coastguard Worker #include "../libdw/memory-access.h"
57*7304104dSAndroid Build Coastguard Worker 
58*7304104dSAndroid Build Coastguard Worker #include "../libdw/known-dwarf.h"
59*7304104dSAndroid Build Coastguard Worker 
60*7304104dSAndroid Build Coastguard Worker #ifdef __linux__
61*7304104dSAndroid Build Coastguard Worker #define CORE_SIGILL  SIGILL
62*7304104dSAndroid Build Coastguard Worker #define CORE_SIGBUS  SIGBUS
63*7304104dSAndroid Build Coastguard Worker #define CORE_SIGFPE  SIGFPE
64*7304104dSAndroid Build Coastguard Worker #define CORE_SIGSEGV SIGSEGV
65*7304104dSAndroid Build Coastguard Worker #define CORE_SI_USER SI_USER
66*7304104dSAndroid Build Coastguard Worker #else
67*7304104dSAndroid Build Coastguard Worker /* We want the linux version of those as that is what shows up in the core files. */
68*7304104dSAndroid Build Coastguard Worker #define CORE_SIGILL  4  /* Illegal instruction (ANSI).  */
69*7304104dSAndroid Build Coastguard Worker #define CORE_SIGBUS  7  /* BUS error (4.2 BSD).  */
70*7304104dSAndroid Build Coastguard Worker #define CORE_SIGFPE  8  /* Floating-point exception (ANSI).  */
71*7304104dSAndroid Build Coastguard Worker #define CORE_SIGSEGV 11 /* Segmentation violation (ANSI).  */
72*7304104dSAndroid Build Coastguard Worker #define CORE_SI_USER 0  /* Sent by kill, sigsend.  */
73*7304104dSAndroid Build Coastguard Worker #endif
74*7304104dSAndroid Build Coastguard Worker 
75*7304104dSAndroid Build Coastguard Worker /* Name and version of program.  */
76*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
77*7304104dSAndroid Build Coastguard Worker 
78*7304104dSAndroid Build Coastguard Worker /* Bug report address.  */
79*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
80*7304104dSAndroid Build Coastguard Worker 
81*7304104dSAndroid Build Coastguard Worker /* argp key value for --elf-section, non-ascii.  */
82*7304104dSAndroid Build Coastguard Worker #define ELF_INPUT_SECTION 256
83*7304104dSAndroid Build Coastguard Worker 
84*7304104dSAndroid Build Coastguard Worker /* argp key value for --dwarf-skeleton, non-ascii.  */
85*7304104dSAndroid Build Coastguard Worker #define DWARF_SKELETON 257
86*7304104dSAndroid Build Coastguard Worker 
87*7304104dSAndroid Build Coastguard Worker /* argp key value for --dyn-syms, non-ascii.  */
88*7304104dSAndroid Build Coastguard Worker #define PRINT_DYNSYM_TABLE 258
89*7304104dSAndroid Build Coastguard Worker 
90*7304104dSAndroid Build Coastguard Worker /* Terrible hack for hooking unrelated skeleton/split compile units,
91*7304104dSAndroid Build Coastguard Worker    see __libdw_link_skel_split in print_debug.  */
92*7304104dSAndroid Build Coastguard Worker static bool do_not_close_dwfl = false;
93*7304104dSAndroid Build Coastguard Worker 
94*7304104dSAndroid Build Coastguard Worker /* Definitions of arguments for argp functions.  */
95*7304104dSAndroid Build Coastguard Worker static const struct argp_option options[] =
96*7304104dSAndroid Build Coastguard Worker {
97*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
98*7304104dSAndroid Build Coastguard Worker   { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
99*7304104dSAndroid Build Coastguard Worker     N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
100*7304104dSAndroid Build Coastguard Worker        "input data"), 0 },
101*7304104dSAndroid Build Coastguard Worker   { "dwarf-skeleton", DWARF_SKELETON, "FILE", 0,
102*7304104dSAndroid Build Coastguard Worker     N_("Used with -w to find the skeleton Compile Units in FILE associated "
103*7304104dSAndroid Build Coastguard Worker        "with the Split Compile units in a .dwo input file"), 0 },
104*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
105*7304104dSAndroid Build Coastguard Worker   { "all", 'a', NULL, 0,
106*7304104dSAndroid Build Coastguard Worker     N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
107*7304104dSAndroid Build Coastguard Worker   { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
108*7304104dSAndroid Build Coastguard Worker   { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
109*7304104dSAndroid Build Coastguard Worker   { "histogram", 'I', NULL, 0,
110*7304104dSAndroid Build Coastguard Worker     N_("Display histogram of bucket list lengths"), 0 },
111*7304104dSAndroid Build Coastguard Worker   { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
112*7304104dSAndroid Build Coastguard Worker   { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
113*7304104dSAndroid Build Coastguard Worker   { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
114*7304104dSAndroid Build Coastguard Worker   { "section-groups", 'g', NULL, 0, N_("Display the section groups"), 0 },
115*7304104dSAndroid Build Coastguard Worker   { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
116*7304104dSAndroid Build Coastguard Worker   { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
117*7304104dSAndroid Build Coastguard Worker   { "symbols", 's', "SECTION", OPTION_ARG_OPTIONAL,
118*7304104dSAndroid Build Coastguard Worker     N_("Display the symbol table sections"), 0 },
119*7304104dSAndroid Build Coastguard Worker   { "syms", 's', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
120*7304104dSAndroid Build Coastguard Worker   { "dyn-syms", PRINT_DYNSYM_TABLE, NULL, 0,
121*7304104dSAndroid Build Coastguard Worker     N_("Display (only) the dynamic symbol table"), 0 },
122*7304104dSAndroid Build Coastguard Worker   { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
123*7304104dSAndroid Build Coastguard Worker   { "notes", 'n', "SECTION", OPTION_ARG_OPTIONAL, N_("Display the ELF notes"), 0 },
124*7304104dSAndroid Build Coastguard Worker   { "arch-specific", 'A', NULL, 0,
125*7304104dSAndroid Build Coastguard Worker     N_("Display architecture specific information, if any"), 0 },
126*7304104dSAndroid Build Coastguard Worker   { "exception", 'e', NULL, 0,
127*7304104dSAndroid Build Coastguard Worker     N_("Display sections for exception handling"), 0 },
128*7304104dSAndroid Build Coastguard Worker 
129*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
130*7304104dSAndroid Build Coastguard Worker   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
131*7304104dSAndroid Build Coastguard Worker     N_("Display DWARF section content.  SECTION can be one of abbrev, addr, "
132*7304104dSAndroid Build Coastguard Worker        "aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
133*7304104dSAndroid Build Coastguard Worker        "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
134*7304104dSAndroid Build Coastguard Worker   { "hex-dump", 'x', "SECTION", 0,
135*7304104dSAndroid Build Coastguard Worker     N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
136*7304104dSAndroid Build Coastguard Worker   { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
137*7304104dSAndroid Build Coastguard Worker     N_("Print string contents of sections"), 0 },
138*7304104dSAndroid Build Coastguard Worker   { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
139*7304104dSAndroid Build Coastguard Worker   { "archive-index", 'c', NULL, 0,
140*7304104dSAndroid Build Coastguard Worker     N_("Display the symbol index of an archive"), 0 },
141*7304104dSAndroid Build Coastguard Worker   { "use-dynamic", 'D', NULL, 0,
142*7304104dSAndroid Build Coastguard Worker     N_("Use the dynamic segment when possible for displaying info"), 0 },
143*7304104dSAndroid Build Coastguard Worker 
144*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, N_("Output control:"), 0 },
145*7304104dSAndroid Build Coastguard Worker   { "numeric-addresses", 'N', NULL, 0,
146*7304104dSAndroid Build Coastguard Worker     N_("Do not find symbol names for addresses in DWARF data"), 0 },
147*7304104dSAndroid Build Coastguard Worker   { "unresolved-address-offsets", 'U', NULL, 0,
148*7304104dSAndroid Build Coastguard Worker     N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
149*7304104dSAndroid Build Coastguard Worker   { "wide", 'W', NULL, 0,
150*7304104dSAndroid Build Coastguard Worker     N_("Ignored for compatibility (lines always wide)"), 0 },
151*7304104dSAndroid Build Coastguard Worker   { "decompress", 'z', NULL, 0,
152*7304104dSAndroid Build Coastguard Worker     N_("Show compression information for compressed sections (when used with -S); decompress section before dumping data (when used with -p or -x)"), 0 },
153*7304104dSAndroid Build Coastguard Worker   { NULL, 0, NULL, 0, NULL, 0 }
154*7304104dSAndroid Build Coastguard Worker };
155*7304104dSAndroid Build Coastguard Worker 
156*7304104dSAndroid Build Coastguard Worker /* Short description of program.  */
157*7304104dSAndroid Build Coastguard Worker static const char doc[] = N_("\
158*7304104dSAndroid Build Coastguard Worker Print information from ELF file in human-readable form.");
159*7304104dSAndroid Build Coastguard Worker 
160*7304104dSAndroid Build Coastguard Worker /* Strings for arguments in help texts.  */
161*7304104dSAndroid Build Coastguard Worker static const char args_doc[] = N_("FILE...");
162*7304104dSAndroid Build Coastguard Worker 
163*7304104dSAndroid Build Coastguard Worker /* Prototype for option handler.  */
164*7304104dSAndroid Build Coastguard Worker static error_t parse_opt (int key, char *arg, struct argp_state *state);
165*7304104dSAndroid Build Coastguard Worker 
166*7304104dSAndroid Build Coastguard Worker /* Data structure to communicate with argp functions.  */
167*7304104dSAndroid Build Coastguard Worker static struct argp argp =
168*7304104dSAndroid Build Coastguard Worker {
169*7304104dSAndroid Build Coastguard Worker   options, parse_opt, args_doc, doc, NULL, NULL, NULL
170*7304104dSAndroid Build Coastguard Worker };
171*7304104dSAndroid Build Coastguard Worker 
172*7304104dSAndroid Build Coastguard Worker /* If non-null, the section from which we should read to (compressed) ELF.  */
173*7304104dSAndroid Build Coastguard Worker static const char *elf_input_section = NULL;
174*7304104dSAndroid Build Coastguard Worker 
175*7304104dSAndroid Build Coastguard Worker /* If non-null, the file that contains the skeleton CUs.  */
176*7304104dSAndroid Build Coastguard Worker static const char *dwarf_skeleton = NULL;
177*7304104dSAndroid Build Coastguard Worker 
178*7304104dSAndroid Build Coastguard Worker /* Flags set by the option controlling the output.  */
179*7304104dSAndroid Build Coastguard Worker 
180*7304104dSAndroid Build Coastguard Worker /* True if dynamic segment should be printed.  */
181*7304104dSAndroid Build Coastguard Worker static bool print_dynamic_table;
182*7304104dSAndroid Build Coastguard Worker 
183*7304104dSAndroid Build Coastguard Worker /* True if the file header should be printed.  */
184*7304104dSAndroid Build Coastguard Worker static bool print_file_header;
185*7304104dSAndroid Build Coastguard Worker 
186*7304104dSAndroid Build Coastguard Worker /* True if the program headers should be printed.  */
187*7304104dSAndroid Build Coastguard Worker static bool print_program_header;
188*7304104dSAndroid Build Coastguard Worker 
189*7304104dSAndroid Build Coastguard Worker /* True if relocations should be printed.  */
190*7304104dSAndroid Build Coastguard Worker static bool print_relocations;
191*7304104dSAndroid Build Coastguard Worker 
192*7304104dSAndroid Build Coastguard Worker /* True if the section headers should be printed.  */
193*7304104dSAndroid Build Coastguard Worker static bool print_section_header;
194*7304104dSAndroid Build Coastguard Worker 
195*7304104dSAndroid Build Coastguard Worker /* True if the symbol table should be printed.  */
196*7304104dSAndroid Build Coastguard Worker static bool print_symbol_table;
197*7304104dSAndroid Build Coastguard Worker 
198*7304104dSAndroid Build Coastguard Worker /* True if (only) the dynsym table should be printed.  */
199*7304104dSAndroid Build Coastguard Worker static bool print_dynsym_table;
200*7304104dSAndroid Build Coastguard Worker 
201*7304104dSAndroid Build Coastguard Worker /* True if reconstruct dynamic symbol table from the PT_DYNAMIC segment.  */
202*7304104dSAndroid Build Coastguard Worker static bool use_dynamic_segment;
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker /* A specific section name, or NULL to print all symbol tables.  */
205*7304104dSAndroid Build Coastguard Worker static char *symbol_table_section;
206*7304104dSAndroid Build Coastguard Worker 
207*7304104dSAndroid Build Coastguard Worker /* A specific section name, or NULL to print all ELF notes.  */
208*7304104dSAndroid Build Coastguard Worker static char *notes_section;
209*7304104dSAndroid Build Coastguard Worker 
210*7304104dSAndroid Build Coastguard Worker /* True if the version information should be printed.  */
211*7304104dSAndroid Build Coastguard Worker static bool print_version_info;
212*7304104dSAndroid Build Coastguard Worker 
213*7304104dSAndroid Build Coastguard Worker /* True if section groups should be printed.  */
214*7304104dSAndroid Build Coastguard Worker static bool print_section_groups;
215*7304104dSAndroid Build Coastguard Worker 
216*7304104dSAndroid Build Coastguard Worker /* True if bucket list length histogram should be printed.  */
217*7304104dSAndroid Build Coastguard Worker static bool print_histogram;
218*7304104dSAndroid Build Coastguard Worker 
219*7304104dSAndroid Build Coastguard Worker /* True if the architecture specific data should be printed.  */
220*7304104dSAndroid Build Coastguard Worker static bool print_arch;
221*7304104dSAndroid Build Coastguard Worker 
222*7304104dSAndroid Build Coastguard Worker /* True if note section content should be printed.  */
223*7304104dSAndroid Build Coastguard Worker static bool print_notes;
224*7304104dSAndroid Build Coastguard Worker 
225*7304104dSAndroid Build Coastguard Worker /* True if SHF_STRINGS section content should be printed.  */
226*7304104dSAndroid Build Coastguard Worker static bool print_string_sections;
227*7304104dSAndroid Build Coastguard Worker 
228*7304104dSAndroid Build Coastguard Worker /* True if archive index should be printed.  */
229*7304104dSAndroid Build Coastguard Worker static bool print_archive_index;
230*7304104dSAndroid Build Coastguard Worker 
231*7304104dSAndroid Build Coastguard Worker /* True if any of the control options except print_archive_index is set.  */
232*7304104dSAndroid Build Coastguard Worker static bool any_control_option;
233*7304104dSAndroid Build Coastguard Worker 
234*7304104dSAndroid Build Coastguard Worker /* True if we should print addresses from DWARF in symbolic form.  */
235*7304104dSAndroid Build Coastguard Worker static bool print_address_names = true;
236*7304104dSAndroid Build Coastguard Worker 
237*7304104dSAndroid Build Coastguard Worker /* True if we should print raw values instead of relativized addresses.  */
238*7304104dSAndroid Build Coastguard Worker static bool print_unresolved_addresses = false;
239*7304104dSAndroid Build Coastguard Worker 
240*7304104dSAndroid Build Coastguard Worker /* True if we should print the .debug_aranges section using libdw.  */
241*7304104dSAndroid Build Coastguard Worker static bool decodedaranges = false;
242*7304104dSAndroid Build Coastguard Worker 
243*7304104dSAndroid Build Coastguard Worker /* True if we should print the .debug_aranges section using libdw.  */
244*7304104dSAndroid Build Coastguard Worker static bool decodedline = false;
245*7304104dSAndroid Build Coastguard Worker 
246*7304104dSAndroid Build Coastguard Worker /* True if we want to show more information about compressed sections.  */
247*7304104dSAndroid Build Coastguard Worker static bool print_decompress = false;
248*7304104dSAndroid Build Coastguard Worker 
249*7304104dSAndroid Build Coastguard Worker /* True if we want to show split compile units for debug_info skeletons.  */
250*7304104dSAndroid Build Coastguard Worker static bool show_split_units = false;
251*7304104dSAndroid Build Coastguard Worker 
252*7304104dSAndroid Build Coastguard Worker /* Select printing of debugging sections.  */
253*7304104dSAndroid Build Coastguard Worker static enum section_e
254*7304104dSAndroid Build Coastguard Worker {
255*7304104dSAndroid Build Coastguard Worker   section_abbrev = 1,		/* .debug_abbrev  */
256*7304104dSAndroid Build Coastguard Worker   section_aranges = 2,		/* .debug_aranges  */
257*7304104dSAndroid Build Coastguard Worker   section_frame = 4,		/* .debug_frame or .eh_frame & al.  */
258*7304104dSAndroid Build Coastguard Worker   section_info = 8,		/* .debug_info, (implies .debug_types)  */
259*7304104dSAndroid Build Coastguard Worker   section_line = 16,		/* .debug_line  */
260*7304104dSAndroid Build Coastguard Worker   section_loc = 32,		/* .debug_loc  */
261*7304104dSAndroid Build Coastguard Worker   section_pubnames = 64,	/* .debug_pubnames  */
262*7304104dSAndroid Build Coastguard Worker   section_str = 128,		/* .debug_str  */
263*7304104dSAndroid Build Coastguard Worker   section_macinfo = 256,	/* .debug_macinfo  */
264*7304104dSAndroid Build Coastguard Worker   section_ranges = 512, 	/* .debug_ranges  */
265*7304104dSAndroid Build Coastguard Worker   section_exception = 1024,	/* .eh_frame & al.  */
266*7304104dSAndroid Build Coastguard Worker   section_gdb_index = 2048,	/* .gdb_index  */
267*7304104dSAndroid Build Coastguard Worker   section_macro = 4096,		/* .debug_macro  */
268*7304104dSAndroid Build Coastguard Worker   section_addr = 8192,		/* .debug_addr  */
269*7304104dSAndroid Build Coastguard Worker   section_types = 16384,	/* .debug_types (implied by .debug_info)  */
270*7304104dSAndroid Build Coastguard Worker   section_all = (section_abbrev | section_aranges | section_frame
271*7304104dSAndroid Build Coastguard Worker 		 | section_info | section_line | section_loc
272*7304104dSAndroid Build Coastguard Worker 		 | section_pubnames | section_str | section_macinfo
273*7304104dSAndroid Build Coastguard Worker 		 | section_ranges | section_exception | section_gdb_index
274*7304104dSAndroid Build Coastguard Worker 		 | section_macro | section_addr | section_types)
275*7304104dSAndroid Build Coastguard Worker } print_debug_sections, implicit_debug_sections;
276*7304104dSAndroid Build Coastguard Worker 
277*7304104dSAndroid Build Coastguard Worker /* Select hex dumping of sections.  */
278*7304104dSAndroid Build Coastguard Worker static struct section_argument *dump_data_sections;
279*7304104dSAndroid Build Coastguard Worker static struct section_argument **dump_data_sections_tail = &dump_data_sections;
280*7304104dSAndroid Build Coastguard Worker 
281*7304104dSAndroid Build Coastguard Worker /* Select string dumping of sections.  */
282*7304104dSAndroid Build Coastguard Worker static struct section_argument *string_sections;
283*7304104dSAndroid Build Coastguard Worker static struct section_argument **string_sections_tail = &string_sections;
284*7304104dSAndroid Build Coastguard Worker 
285*7304104dSAndroid Build Coastguard Worker struct section_argument
286*7304104dSAndroid Build Coastguard Worker {
287*7304104dSAndroid Build Coastguard Worker   struct section_argument *next;
288*7304104dSAndroid Build Coastguard Worker   const char *arg;
289*7304104dSAndroid Build Coastguard Worker   bool implicit;
290*7304104dSAndroid Build Coastguard Worker };
291*7304104dSAndroid Build Coastguard Worker 
292*7304104dSAndroid Build Coastguard Worker /* Numbers of sections and program headers in the file.  */
293*7304104dSAndroid Build Coastguard Worker static size_t shnum;
294*7304104dSAndroid Build Coastguard Worker static size_t phnum;
295*7304104dSAndroid Build Coastguard Worker 
296*7304104dSAndroid Build Coastguard Worker 
297*7304104dSAndroid Build Coastguard Worker /* Declarations of local functions.  */
298*7304104dSAndroid Build Coastguard Worker static void process_file (int fd, const char *fname, bool only_one);
299*7304104dSAndroid Build Coastguard Worker static void process_elf_file (Dwfl_Module *dwflmod, int fd);
300*7304104dSAndroid Build Coastguard Worker static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
301*7304104dSAndroid Build Coastguard Worker static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
302*7304104dSAndroid Build Coastguard Worker static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
303*7304104dSAndroid Build Coastguard Worker static void print_scngrp (Ebl *ebl);
304*7304104dSAndroid Build Coastguard Worker static void print_dynamic (Ebl *ebl);
305*7304104dSAndroid Build Coastguard Worker static void print_relocs (Ebl *ebl, Dwfl_Module *mod, GElf_Ehdr *ehdr);
306*7304104dSAndroid Build Coastguard Worker static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
307*7304104dSAndroid Build Coastguard Worker 			       GElf_Shdr *shdr);
308*7304104dSAndroid Build Coastguard Worker static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
309*7304104dSAndroid Build Coastguard Worker 				GElf_Shdr *shdr);
310*7304104dSAndroid Build Coastguard Worker static void handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn,
311*7304104dSAndroid Build Coastguard Worker 				GElf_Shdr *shdr);
312*7304104dSAndroid Build Coastguard Worker static bool print_symtab (Ebl *ebl, int type);
313*7304104dSAndroid Build Coastguard Worker static bool handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
314*7304104dSAndroid Build Coastguard Worker static bool handle_dynamic_symtab (Ebl *ebl);
315*7304104dSAndroid Build Coastguard Worker static void
316*7304104dSAndroid Build Coastguard Worker process_symtab(
317*7304104dSAndroid Build Coastguard Worker 	Ebl * ebl,
318*7304104dSAndroid Build Coastguard Worker 	unsigned int nsyms,
319*7304104dSAndroid Build Coastguard Worker 	Elf64_Word idx,
320*7304104dSAndroid Build Coastguard Worker 	Elf32_Word verneed_stridx,
321*7304104dSAndroid Build Coastguard Worker 	Elf32_Word verdef_stridx,
322*7304104dSAndroid Build Coastguard Worker 	Elf_Data * symdata,
323*7304104dSAndroid Build Coastguard Worker 	Elf_Data * versym_data,
324*7304104dSAndroid Build Coastguard Worker 	Elf_Data * symstr_data,
325*7304104dSAndroid Build Coastguard Worker 	Elf_Data * verneed_data,
326*7304104dSAndroid Build Coastguard Worker 	Elf_Data * verdef_data,
327*7304104dSAndroid Build Coastguard Worker 	Elf_Data * xndx_data);
328*7304104dSAndroid Build Coastguard Worker static void print_verinfo (Ebl *ebl);
329*7304104dSAndroid Build Coastguard Worker static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
330*7304104dSAndroid Build Coastguard Worker static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
331*7304104dSAndroid Build Coastguard Worker static void handle_versym (Ebl *ebl, Elf_Scn *scn,
332*7304104dSAndroid Build Coastguard Worker 			   GElf_Shdr *shdr);
333*7304104dSAndroid Build Coastguard Worker static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
334*7304104dSAndroid Build Coastguard Worker static void handle_hash (Ebl *ebl);
335*7304104dSAndroid Build Coastguard Worker static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
336*7304104dSAndroid Build Coastguard Worker static void print_liblist (Ebl *ebl);
337*7304104dSAndroid Build Coastguard Worker static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
338*7304104dSAndroid Build Coastguard Worker static void dump_data (Ebl *ebl);
339*7304104dSAndroid Build Coastguard Worker static void dump_strings (Ebl *ebl);
340*7304104dSAndroid Build Coastguard Worker static void print_strings (Ebl *ebl);
341*7304104dSAndroid Build Coastguard Worker static void dump_archive_index (Elf *, const char *);
342*7304104dSAndroid Build Coastguard Worker static void print_dwarf_addr (Dwfl_Module *dwflmod, int address_size,
343*7304104dSAndroid Build Coastguard Worker 			      Dwarf_Addr address, Dwarf_Addr raw);
344*7304104dSAndroid Build Coastguard Worker 
345*7304104dSAndroid Build Coastguard Worker enum dyn_idx
346*7304104dSAndroid Build Coastguard Worker {
347*7304104dSAndroid Build Coastguard Worker   i_symtab_shndx,
348*7304104dSAndroid Build Coastguard Worker   i_strsz,
349*7304104dSAndroid Build Coastguard Worker   i_verneed,
350*7304104dSAndroid Build Coastguard Worker   i_verneednum,
351*7304104dSAndroid Build Coastguard Worker   i_verdef,
352*7304104dSAndroid Build Coastguard Worker   i_verdefnum,
353*7304104dSAndroid Build Coastguard Worker   i_versym,
354*7304104dSAndroid Build Coastguard Worker   i_symtab,
355*7304104dSAndroid Build Coastguard Worker   i_strtab,
356*7304104dSAndroid Build Coastguard Worker   i_hash,
357*7304104dSAndroid Build Coastguard Worker   i_gnu_hash,
358*7304104dSAndroid Build Coastguard Worker   i_max
359*7304104dSAndroid Build Coastguard Worker };
360*7304104dSAndroid Build Coastguard Worker 
361*7304104dSAndroid Build Coastguard Worker /* Declarations of local functions for use-dynamic.  */
362*7304104dSAndroid Build Coastguard Worker static Elf_Data *get_dynscn_strtab (Elf *elf, GElf_Phdr *phdr);
363*7304104dSAndroid Build Coastguard Worker static void get_dynscn_addrs (Elf *elf, GElf_Phdr *phdr, GElf_Addr addrs[i_max]);
364*7304104dSAndroid Build Coastguard Worker static void find_offsets (Elf *elf, GElf_Addr main_bias, size_t n,
365*7304104dSAndroid Build Coastguard Worker 			  GElf_Addr addrs[n], GElf_Off offs[n]);
366*7304104dSAndroid Build Coastguard Worker 
367*7304104dSAndroid Build Coastguard Worker /* Looked up once with gettext in main.  */
368*7304104dSAndroid Build Coastguard Worker static char *yes_str;
369*7304104dSAndroid Build Coastguard Worker static char *no_str;
370*7304104dSAndroid Build Coastguard Worker 
371*7304104dSAndroid Build Coastguard Worker static void
cleanup_list(struct section_argument * list)372*7304104dSAndroid Build Coastguard Worker cleanup_list (struct section_argument *list)
373*7304104dSAndroid Build Coastguard Worker {
374*7304104dSAndroid Build Coastguard Worker   while (list != NULL)
375*7304104dSAndroid Build Coastguard Worker     {
376*7304104dSAndroid Build Coastguard Worker       struct section_argument *a = list;
377*7304104dSAndroid Build Coastguard Worker       list = a->next;
378*7304104dSAndroid Build Coastguard Worker       free (a);
379*7304104dSAndroid Build Coastguard Worker     }
380*7304104dSAndroid Build Coastguard Worker }
381*7304104dSAndroid Build Coastguard Worker 
382*7304104dSAndroid Build Coastguard Worker int
main(int argc,char * argv[])383*7304104dSAndroid Build Coastguard Worker main (int argc, char *argv[])
384*7304104dSAndroid Build Coastguard Worker {
385*7304104dSAndroid Build Coastguard Worker   /* We use no threads here which can interfere with handling a stream.  */
386*7304104dSAndroid Build Coastguard Worker   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
387*7304104dSAndroid Build Coastguard Worker 
388*7304104dSAndroid Build Coastguard Worker   /* Set locale.  */
389*7304104dSAndroid Build Coastguard Worker   setlocale (LC_ALL, "");
390*7304104dSAndroid Build Coastguard Worker 
391*7304104dSAndroid Build Coastguard Worker   /* Initialize the message catalog.  */
392*7304104dSAndroid Build Coastguard Worker   textdomain (PACKAGE_TARNAME);
393*7304104dSAndroid Build Coastguard Worker 
394*7304104dSAndroid Build Coastguard Worker   /* Look up once.  */
395*7304104dSAndroid Build Coastguard Worker   yes_str = _("yes");
396*7304104dSAndroid Build Coastguard Worker   no_str = _("no");
397*7304104dSAndroid Build Coastguard Worker 
398*7304104dSAndroid Build Coastguard Worker   /* Parse and process arguments.  */
399*7304104dSAndroid Build Coastguard Worker   int remaining;
400*7304104dSAndroid Build Coastguard Worker   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
401*7304104dSAndroid Build Coastguard Worker 
402*7304104dSAndroid Build Coastguard Worker   /* Before we start tell the ELF library which version we are using.  */
403*7304104dSAndroid Build Coastguard Worker   elf_version (EV_CURRENT);
404*7304104dSAndroid Build Coastguard Worker 
405*7304104dSAndroid Build Coastguard Worker   /* Now process all the files given at the command line.  */
406*7304104dSAndroid Build Coastguard Worker   bool only_one = remaining + 1 == argc;
407*7304104dSAndroid Build Coastguard Worker   do
408*7304104dSAndroid Build Coastguard Worker     {
409*7304104dSAndroid Build Coastguard Worker       /* Open the file.  */
410*7304104dSAndroid Build Coastguard Worker       int fd = open (argv[remaining], O_RDONLY);
411*7304104dSAndroid Build Coastguard Worker       if (fd == -1)
412*7304104dSAndroid Build Coastguard Worker 	{
413*7304104dSAndroid Build Coastguard Worker 	  error (0, errno, _("cannot open input file '%s'"), argv[remaining]);
414*7304104dSAndroid Build Coastguard Worker 	  continue;
415*7304104dSAndroid Build Coastguard Worker 	}
416*7304104dSAndroid Build Coastguard Worker 
417*7304104dSAndroid Build Coastguard Worker       process_file (fd, argv[remaining], only_one);
418*7304104dSAndroid Build Coastguard Worker 
419*7304104dSAndroid Build Coastguard Worker       close (fd);
420*7304104dSAndroid Build Coastguard Worker     }
421*7304104dSAndroid Build Coastguard Worker   while (++remaining < argc);
422*7304104dSAndroid Build Coastguard Worker 
423*7304104dSAndroid Build Coastguard Worker   cleanup_list (dump_data_sections);
424*7304104dSAndroid Build Coastguard Worker   cleanup_list (string_sections);
425*7304104dSAndroid Build Coastguard Worker 
426*7304104dSAndroid Build Coastguard Worker   return error_message_count != 0;
427*7304104dSAndroid Build Coastguard Worker }
428*7304104dSAndroid Build Coastguard Worker 
429*7304104dSAndroid Build Coastguard Worker static void
add_dump_section(const char * name,int key,bool implicit)430*7304104dSAndroid Build Coastguard Worker add_dump_section (const char *name,
431*7304104dSAndroid Build Coastguard Worker 		  int key,
432*7304104dSAndroid Build Coastguard Worker 		  bool implicit)
433*7304104dSAndroid Build Coastguard Worker {
434*7304104dSAndroid Build Coastguard Worker   struct section_argument *a = xmalloc (sizeof *a);
435*7304104dSAndroid Build Coastguard Worker   a->arg = name;
436*7304104dSAndroid Build Coastguard Worker   a->next = NULL;
437*7304104dSAndroid Build Coastguard Worker   a->implicit = implicit;
438*7304104dSAndroid Build Coastguard Worker   struct section_argument ***tailp
439*7304104dSAndroid Build Coastguard Worker     = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
440*7304104dSAndroid Build Coastguard Worker   **tailp = a;
441*7304104dSAndroid Build Coastguard Worker   *tailp = &a->next;
442*7304104dSAndroid Build Coastguard Worker }
443*7304104dSAndroid Build Coastguard Worker 
444*7304104dSAndroid Build Coastguard Worker /* Handle program arguments.  */
445*7304104dSAndroid Build Coastguard Worker static error_t
parse_opt(int key,char * arg,struct argp_state * state)446*7304104dSAndroid Build Coastguard Worker parse_opt (int key, char *arg,
447*7304104dSAndroid Build Coastguard Worker 	   struct argp_state *state __attribute__ ((unused)))
448*7304104dSAndroid Build Coastguard Worker {
449*7304104dSAndroid Build Coastguard Worker   switch (key)
450*7304104dSAndroid Build Coastguard Worker     {
451*7304104dSAndroid Build Coastguard Worker     case 'a':
452*7304104dSAndroid Build Coastguard Worker       print_file_header = true;
453*7304104dSAndroid Build Coastguard Worker       print_program_header = true;
454*7304104dSAndroid Build Coastguard Worker       print_relocations = true;
455*7304104dSAndroid Build Coastguard Worker       print_section_header = true;
456*7304104dSAndroid Build Coastguard Worker       print_symbol_table = true;
457*7304104dSAndroid Build Coastguard Worker       print_version_info = true;
458*7304104dSAndroid Build Coastguard Worker       print_dynamic_table = true;
459*7304104dSAndroid Build Coastguard Worker       print_section_groups = true;
460*7304104dSAndroid Build Coastguard Worker       print_histogram = true;
461*7304104dSAndroid Build Coastguard Worker       print_arch = true;
462*7304104dSAndroid Build Coastguard Worker       print_notes = true;
463*7304104dSAndroid Build Coastguard Worker       implicit_debug_sections |= section_exception;
464*7304104dSAndroid Build Coastguard Worker       add_dump_section (".strtab", key, true);
465*7304104dSAndroid Build Coastguard Worker       add_dump_section (".dynstr", key, true);
466*7304104dSAndroid Build Coastguard Worker       add_dump_section (".comment", key, true);
467*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
468*7304104dSAndroid Build Coastguard Worker       break;
469*7304104dSAndroid Build Coastguard Worker     case 'A':
470*7304104dSAndroid Build Coastguard Worker       print_arch = true;
471*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
472*7304104dSAndroid Build Coastguard Worker       break;
473*7304104dSAndroid Build Coastguard Worker     case 'd':
474*7304104dSAndroid Build Coastguard Worker       print_dynamic_table = true;
475*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
476*7304104dSAndroid Build Coastguard Worker       break;
477*7304104dSAndroid Build Coastguard Worker     case 'D':
478*7304104dSAndroid Build Coastguard Worker       use_dynamic_segment = true;
479*7304104dSAndroid Build Coastguard Worker       break;
480*7304104dSAndroid Build Coastguard Worker     case 'e':
481*7304104dSAndroid Build Coastguard Worker       print_debug_sections |= section_exception;
482*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
483*7304104dSAndroid Build Coastguard Worker       break;
484*7304104dSAndroid Build Coastguard Worker     case 'g':
485*7304104dSAndroid Build Coastguard Worker       print_section_groups = true;
486*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
487*7304104dSAndroid Build Coastguard Worker       break;
488*7304104dSAndroid Build Coastguard Worker     case 'h':
489*7304104dSAndroid Build Coastguard Worker       print_file_header = true;
490*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
491*7304104dSAndroid Build Coastguard Worker       break;
492*7304104dSAndroid Build Coastguard Worker     case 'I':
493*7304104dSAndroid Build Coastguard Worker       print_histogram = true;
494*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
495*7304104dSAndroid Build Coastguard Worker       break;
496*7304104dSAndroid Build Coastguard Worker     case 'l':
497*7304104dSAndroid Build Coastguard Worker       print_program_header = true;
498*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
499*7304104dSAndroid Build Coastguard Worker       break;
500*7304104dSAndroid Build Coastguard Worker     case 'n':
501*7304104dSAndroid Build Coastguard Worker       print_notes = true;
502*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
503*7304104dSAndroid Build Coastguard Worker       notes_section = arg;
504*7304104dSAndroid Build Coastguard Worker       break;
505*7304104dSAndroid Build Coastguard Worker     case 'r':
506*7304104dSAndroid Build Coastguard Worker       print_relocations = true;
507*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
508*7304104dSAndroid Build Coastguard Worker      break;
509*7304104dSAndroid Build Coastguard Worker     case 'S':
510*7304104dSAndroid Build Coastguard Worker       print_section_header = true;
511*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
512*7304104dSAndroid Build Coastguard Worker       break;
513*7304104dSAndroid Build Coastguard Worker     case 's':
514*7304104dSAndroid Build Coastguard Worker       print_symbol_table = true;
515*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
516*7304104dSAndroid Build Coastguard Worker       symbol_table_section = arg;
517*7304104dSAndroid Build Coastguard Worker       break;
518*7304104dSAndroid Build Coastguard Worker     case PRINT_DYNSYM_TABLE:
519*7304104dSAndroid Build Coastguard Worker       print_dynsym_table = true;
520*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
521*7304104dSAndroid Build Coastguard Worker       break;
522*7304104dSAndroid Build Coastguard Worker     case 'V':
523*7304104dSAndroid Build Coastguard Worker       print_version_info = true;
524*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
525*7304104dSAndroid Build Coastguard Worker       break;
526*7304104dSAndroid Build Coastguard Worker     case 'c':
527*7304104dSAndroid Build Coastguard Worker       print_archive_index = true;
528*7304104dSAndroid Build Coastguard Worker       break;
529*7304104dSAndroid Build Coastguard Worker     case 'w':
530*7304104dSAndroid Build Coastguard Worker       if (arg == NULL)
531*7304104dSAndroid Build Coastguard Worker 	{
532*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections = section_all;
533*7304104dSAndroid Build Coastguard Worker 	  implicit_debug_sections = section_info;
534*7304104dSAndroid Build Coastguard Worker 	  show_split_units = true;
535*7304104dSAndroid Build Coastguard Worker 	}
536*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "abbrev") == 0)
537*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_abbrev;
538*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "addr") == 0)
539*7304104dSAndroid Build Coastguard Worker 	{
540*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_addr;
541*7304104dSAndroid Build Coastguard Worker 	  implicit_debug_sections |= section_info;
542*7304104dSAndroid Build Coastguard Worker 	}
543*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "aranges") == 0)
544*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_aranges;
545*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "decodedaranges") == 0)
546*7304104dSAndroid Build Coastguard Worker 	{
547*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_aranges;
548*7304104dSAndroid Build Coastguard Worker 	  decodedaranges = true;
549*7304104dSAndroid Build Coastguard Worker 	}
550*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "ranges") == 0)
551*7304104dSAndroid Build Coastguard Worker 	{
552*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_ranges;
553*7304104dSAndroid Build Coastguard Worker 	  implicit_debug_sections |= section_info;
554*7304104dSAndroid Build Coastguard Worker 	}
555*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
556*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_frame;
557*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "info") == 0)
558*7304104dSAndroid Build Coastguard Worker 	{
559*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_info;
560*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_types;
561*7304104dSAndroid Build Coastguard Worker 	}
562*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "info+") == 0)
563*7304104dSAndroid Build Coastguard Worker 	{
564*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_info;
565*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_types;
566*7304104dSAndroid Build Coastguard Worker 	  show_split_units = true;
567*7304104dSAndroid Build Coastguard Worker 	}
568*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "loc") == 0)
569*7304104dSAndroid Build Coastguard Worker 	{
570*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_loc;
571*7304104dSAndroid Build Coastguard Worker 	  implicit_debug_sections |= section_info;
572*7304104dSAndroid Build Coastguard Worker 	}
573*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "line") == 0)
574*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_line;
575*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "decodedline") == 0)
576*7304104dSAndroid Build Coastguard Worker 	{
577*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_line;
578*7304104dSAndroid Build Coastguard Worker 	  decodedline = true;
579*7304104dSAndroid Build Coastguard Worker 	}
580*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "pubnames") == 0)
581*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_pubnames;
582*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "str") == 0)
583*7304104dSAndroid Build Coastguard Worker 	{
584*7304104dSAndroid Build Coastguard Worker 	  print_debug_sections |= section_str;
585*7304104dSAndroid Build Coastguard Worker 	  /* For mapping string offset tables to CUs.  */
586*7304104dSAndroid Build Coastguard Worker 	  implicit_debug_sections |= section_info;
587*7304104dSAndroid Build Coastguard Worker 	}
588*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "macinfo") == 0)
589*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_macinfo;
590*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "macro") == 0)
591*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_macro;
592*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "exception") == 0)
593*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_exception;
594*7304104dSAndroid Build Coastguard Worker       else if (strcmp (arg, "gdb_index") == 0)
595*7304104dSAndroid Build Coastguard Worker 	print_debug_sections |= section_gdb_index;
596*7304104dSAndroid Build Coastguard Worker       else
597*7304104dSAndroid Build Coastguard Worker 	{
598*7304104dSAndroid Build Coastguard Worker 	  fprintf (stderr, _("Unknown DWARF debug section `%s'.\n"),
599*7304104dSAndroid Build Coastguard Worker 		   arg);
600*7304104dSAndroid Build Coastguard Worker 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
601*7304104dSAndroid Build Coastguard Worker 		     program_invocation_short_name);
602*7304104dSAndroid Build Coastguard Worker 	  exit (1);
603*7304104dSAndroid Build Coastguard Worker 	}
604*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
605*7304104dSAndroid Build Coastguard Worker       break;
606*7304104dSAndroid Build Coastguard Worker     case 'p':
607*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
608*7304104dSAndroid Build Coastguard Worker       if (arg == NULL)
609*7304104dSAndroid Build Coastguard Worker 	{
610*7304104dSAndroid Build Coastguard Worker 	  print_string_sections = true;
611*7304104dSAndroid Build Coastguard Worker 	  break;
612*7304104dSAndroid Build Coastguard Worker 	}
613*7304104dSAndroid Build Coastguard Worker       FALLTHROUGH;
614*7304104dSAndroid Build Coastguard Worker     case 'x':
615*7304104dSAndroid Build Coastguard Worker       add_dump_section (arg, key, false);
616*7304104dSAndroid Build Coastguard Worker       any_control_option = true;
617*7304104dSAndroid Build Coastguard Worker       break;
618*7304104dSAndroid Build Coastguard Worker     case 'N':
619*7304104dSAndroid Build Coastguard Worker       print_address_names = false;
620*7304104dSAndroid Build Coastguard Worker       break;
621*7304104dSAndroid Build Coastguard Worker     case 'U':
622*7304104dSAndroid Build Coastguard Worker       print_unresolved_addresses = true;
623*7304104dSAndroid Build Coastguard Worker       break;
624*7304104dSAndroid Build Coastguard Worker     case ARGP_KEY_NO_ARGS:
625*7304104dSAndroid Build Coastguard Worker       fputs (_("Missing file name.\n"), stderr);
626*7304104dSAndroid Build Coastguard Worker       goto do_argp_help;
627*7304104dSAndroid Build Coastguard Worker     case ARGP_KEY_FINI:
628*7304104dSAndroid Build Coastguard Worker       if (! any_control_option && ! print_archive_index)
629*7304104dSAndroid Build Coastguard Worker 	{
630*7304104dSAndroid Build Coastguard Worker 	  fputs (_("No operation specified.\n"), stderr);
631*7304104dSAndroid Build Coastguard Worker 	do_argp_help:
632*7304104dSAndroid Build Coastguard Worker 	  argp_help (&argp, stderr, ARGP_HELP_SEE,
633*7304104dSAndroid Build Coastguard Worker 		     program_invocation_short_name);
634*7304104dSAndroid Build Coastguard Worker 	  exit (EXIT_FAILURE);
635*7304104dSAndroid Build Coastguard Worker 	}
636*7304104dSAndroid Build Coastguard Worker       break;
637*7304104dSAndroid Build Coastguard Worker     case 'W':			/* Ignored.  */
638*7304104dSAndroid Build Coastguard Worker       break;
639*7304104dSAndroid Build Coastguard Worker     case 'z':
640*7304104dSAndroid Build Coastguard Worker       print_decompress = true;
641*7304104dSAndroid Build Coastguard Worker       break;
642*7304104dSAndroid Build Coastguard Worker     case ELF_INPUT_SECTION:
643*7304104dSAndroid Build Coastguard Worker       if (arg == NULL)
644*7304104dSAndroid Build Coastguard Worker 	elf_input_section = ".gnu_debugdata";
645*7304104dSAndroid Build Coastguard Worker       else
646*7304104dSAndroid Build Coastguard Worker 	elf_input_section = arg;
647*7304104dSAndroid Build Coastguard Worker       break;
648*7304104dSAndroid Build Coastguard Worker     case DWARF_SKELETON:
649*7304104dSAndroid Build Coastguard Worker       dwarf_skeleton = arg;
650*7304104dSAndroid Build Coastguard Worker       break;
651*7304104dSAndroid Build Coastguard Worker     default:
652*7304104dSAndroid Build Coastguard Worker       return ARGP_ERR_UNKNOWN;
653*7304104dSAndroid Build Coastguard Worker     }
654*7304104dSAndroid Build Coastguard Worker   return 0;
655*7304104dSAndroid Build Coastguard Worker }
656*7304104dSAndroid Build Coastguard Worker 
657*7304104dSAndroid Build Coastguard Worker 
658*7304104dSAndroid Build Coastguard Worker /* Create a file descriptor to read the data from the
659*7304104dSAndroid Build Coastguard Worker    elf_input_section given a file descriptor to an ELF file.  */
660*7304104dSAndroid Build Coastguard Worker static int
open_input_section(int fd)661*7304104dSAndroid Build Coastguard Worker open_input_section (int fd)
662*7304104dSAndroid Build Coastguard Worker {
663*7304104dSAndroid Build Coastguard Worker   size_t shnums;
664*7304104dSAndroid Build Coastguard Worker   size_t cnt;
665*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
666*7304104dSAndroid Build Coastguard Worker   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
667*7304104dSAndroid Build Coastguard Worker   if (elf == NULL)
668*7304104dSAndroid Build Coastguard Worker     {
669*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot generate Elf descriptor: %s"),
670*7304104dSAndroid Build Coastguard Worker 	     elf_errmsg (-1));
671*7304104dSAndroid Build Coastguard Worker       return -1;
672*7304104dSAndroid Build Coastguard Worker     }
673*7304104dSAndroid Build Coastguard Worker 
674*7304104dSAndroid Build Coastguard Worker   if (elf_getshdrnum (elf, &shnums) < 0)
675*7304104dSAndroid Build Coastguard Worker     {
676*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot determine number of sections: %s"),
677*7304104dSAndroid Build Coastguard Worker 	     elf_errmsg (-1));
678*7304104dSAndroid Build Coastguard Worker     open_error:
679*7304104dSAndroid Build Coastguard Worker       elf_end (elf);
680*7304104dSAndroid Build Coastguard Worker       return -1;
681*7304104dSAndroid Build Coastguard Worker     }
682*7304104dSAndroid Build Coastguard Worker 
683*7304104dSAndroid Build Coastguard Worker   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
684*7304104dSAndroid Build Coastguard Worker     {
685*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get section header string table index"));
686*7304104dSAndroid Build Coastguard Worker       goto open_error;
687*7304104dSAndroid Build Coastguard Worker     }
688*7304104dSAndroid Build Coastguard Worker 
689*7304104dSAndroid Build Coastguard Worker   for (cnt = 0; cnt < shnums; ++cnt)
690*7304104dSAndroid Build Coastguard Worker     {
691*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn = elf_getscn (elf, cnt);
692*7304104dSAndroid Build Coastguard Worker       if (scn == NULL)
693*7304104dSAndroid Build Coastguard Worker 	{
694*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot get section: %s"),
695*7304104dSAndroid Build Coastguard Worker 		 elf_errmsg (-1));
696*7304104dSAndroid Build Coastguard Worker 	  goto open_error;
697*7304104dSAndroid Build Coastguard Worker 	}
698*7304104dSAndroid Build Coastguard Worker 
699*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
700*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
701*7304104dSAndroid Build Coastguard Worker       if (unlikely (shdr == NULL))
702*7304104dSAndroid Build Coastguard Worker 	{
703*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot get section header: %s"),
704*7304104dSAndroid Build Coastguard Worker 		 elf_errmsg (-1));
705*7304104dSAndroid Build Coastguard Worker 	  goto open_error;
706*7304104dSAndroid Build Coastguard Worker 	}
707*7304104dSAndroid Build Coastguard Worker 
708*7304104dSAndroid Build Coastguard Worker       const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
709*7304104dSAndroid Build Coastguard Worker       if (sname == NULL)
710*7304104dSAndroid Build Coastguard Worker 	{
711*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot get section name"));
712*7304104dSAndroid Build Coastguard Worker 	  goto open_error;
713*7304104dSAndroid Build Coastguard Worker 	}
714*7304104dSAndroid Build Coastguard Worker 
715*7304104dSAndroid Build Coastguard Worker       if (strcmp (sname, elf_input_section) == 0)
716*7304104dSAndroid Build Coastguard Worker 	{
717*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *data = elf_rawdata (scn, NULL);
718*7304104dSAndroid Build Coastguard Worker 	  if (data == NULL)
719*7304104dSAndroid Build Coastguard Worker 	    {
720*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("cannot get %s content: %s"),
721*7304104dSAndroid Build Coastguard Worker 		     sname, elf_errmsg (-1));
722*7304104dSAndroid Build Coastguard Worker 	      goto open_error;
723*7304104dSAndroid Build Coastguard Worker 	    }
724*7304104dSAndroid Build Coastguard Worker 
725*7304104dSAndroid Build Coastguard Worker 	  /* Create (and immediately unlink) a temporary file to store
726*7304104dSAndroid Build Coastguard Worker 	     section data in to create a file descriptor for it.  */
727*7304104dSAndroid Build Coastguard Worker 	  const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
728*7304104dSAndroid Build Coastguard Worker 	  static const char suffix[] = "/readelfXXXXXX";
729*7304104dSAndroid Build Coastguard Worker 	  int tmplen = strlen (tmpdir) + sizeof (suffix);
730*7304104dSAndroid Build Coastguard Worker 	  char *tempname = alloca (tmplen);
731*7304104dSAndroid Build Coastguard Worker 	  sprintf (tempname, "%s%s", tmpdir, suffix);
732*7304104dSAndroid Build Coastguard Worker 
733*7304104dSAndroid Build Coastguard Worker 	  int sfd = mkstemp (tempname);
734*7304104dSAndroid Build Coastguard Worker 	  if (sfd == -1)
735*7304104dSAndroid Build Coastguard Worker 	    {
736*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("cannot create temp file '%s'"),
737*7304104dSAndroid Build Coastguard Worker 		     tempname);
738*7304104dSAndroid Build Coastguard Worker 	      goto open_error;
739*7304104dSAndroid Build Coastguard Worker 	    }
740*7304104dSAndroid Build Coastguard Worker 	  unlink (tempname);
741*7304104dSAndroid Build Coastguard Worker 
742*7304104dSAndroid Build Coastguard Worker 	  ssize_t size = data->d_size;
743*7304104dSAndroid Build Coastguard Worker 	  if (write_retry (sfd, data->d_buf, size) != size)
744*7304104dSAndroid Build Coastguard Worker 	    {
745*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("cannot write section data"));
746*7304104dSAndroid Build Coastguard Worker 	      goto open_error;
747*7304104dSAndroid Build Coastguard Worker 	    }
748*7304104dSAndroid Build Coastguard Worker 
749*7304104dSAndroid Build Coastguard Worker 	  if (elf_end (elf) != 0)
750*7304104dSAndroid Build Coastguard Worker 	    {
751*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("error while closing Elf descriptor: %s"),
752*7304104dSAndroid Build Coastguard Worker 		     elf_errmsg (-1));
753*7304104dSAndroid Build Coastguard Worker 	      return -1;
754*7304104dSAndroid Build Coastguard Worker 	    }
755*7304104dSAndroid Build Coastguard Worker 
756*7304104dSAndroid Build Coastguard Worker 	  if (lseek (sfd, 0, SEEK_SET) == -1)
757*7304104dSAndroid Build Coastguard Worker 	    {
758*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("error while rewinding file descriptor"));
759*7304104dSAndroid Build Coastguard Worker 	      return -1;
760*7304104dSAndroid Build Coastguard Worker 	    }
761*7304104dSAndroid Build Coastguard Worker 
762*7304104dSAndroid Build Coastguard Worker 	  return sfd;
763*7304104dSAndroid Build Coastguard Worker 	}
764*7304104dSAndroid Build Coastguard Worker     }
765*7304104dSAndroid Build Coastguard Worker 
766*7304104dSAndroid Build Coastguard Worker   /* Named section not found.  */
767*7304104dSAndroid Build Coastguard Worker   if (elf_end (elf) != 0)
768*7304104dSAndroid Build Coastguard Worker     error (0, 0, _("error while closing Elf descriptor: %s"),
769*7304104dSAndroid Build Coastguard Worker 	   elf_errmsg (-1));
770*7304104dSAndroid Build Coastguard Worker   return -1;
771*7304104dSAndroid Build Coastguard Worker }
772*7304104dSAndroid Build Coastguard Worker 
773*7304104dSAndroid Build Coastguard Worker /* Check if the file is an archive, and if so dump its index.  */
774*7304104dSAndroid Build Coastguard Worker static void
check_archive_index(int fd,const char * fname,bool only_one)775*7304104dSAndroid Build Coastguard Worker check_archive_index (int fd, const char *fname, bool only_one)
776*7304104dSAndroid Build Coastguard Worker {
777*7304104dSAndroid Build Coastguard Worker   /* Create an `Elf' descriptor.  */
778*7304104dSAndroid Build Coastguard Worker   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
779*7304104dSAndroid Build Coastguard Worker   if (elf == NULL)
780*7304104dSAndroid Build Coastguard Worker     error (0, 0, _("cannot generate Elf descriptor: %s"),
781*7304104dSAndroid Build Coastguard Worker 	   elf_errmsg (-1));
782*7304104dSAndroid Build Coastguard Worker   else
783*7304104dSAndroid Build Coastguard Worker     {
784*7304104dSAndroid Build Coastguard Worker       if (elf_kind (elf) == ELF_K_AR)
785*7304104dSAndroid Build Coastguard Worker 	{
786*7304104dSAndroid Build Coastguard Worker 	  if (!only_one)
787*7304104dSAndroid Build Coastguard Worker 	    printf ("\n%s:\n\n", fname);
788*7304104dSAndroid Build Coastguard Worker 	  dump_archive_index (elf, fname);
789*7304104dSAndroid Build Coastguard Worker 	}
790*7304104dSAndroid Build Coastguard Worker       else
791*7304104dSAndroid Build Coastguard Worker 	error (0, 0,
792*7304104dSAndroid Build Coastguard Worker 	       _("'%s' is not an archive, cannot print archive index"),
793*7304104dSAndroid Build Coastguard Worker 	       fname);
794*7304104dSAndroid Build Coastguard Worker 
795*7304104dSAndroid Build Coastguard Worker       /* Now we can close the descriptor.  */
796*7304104dSAndroid Build Coastguard Worker       if (elf_end (elf) != 0)
797*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("error while closing Elf descriptor: %s"),
798*7304104dSAndroid Build Coastguard Worker 	       elf_errmsg (-1));
799*7304104dSAndroid Build Coastguard Worker     }
800*7304104dSAndroid Build Coastguard Worker }
801*7304104dSAndroid Build Coastguard Worker 
802*7304104dSAndroid Build Coastguard Worker /* Trivial callback used for checking if we opened an archive.  */
803*7304104dSAndroid Build Coastguard Worker static int
count_dwflmod(Dwfl_Module * dwflmod,void ** userdata,const char * name,Dwarf_Addr base,void * arg)804*7304104dSAndroid Build Coastguard Worker count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
805*7304104dSAndroid Build Coastguard Worker 	       void **userdata __attribute__ ((unused)),
806*7304104dSAndroid Build Coastguard Worker 	       const char *name __attribute__ ((unused)),
807*7304104dSAndroid Build Coastguard Worker 	       Dwarf_Addr base __attribute__ ((unused)),
808*7304104dSAndroid Build Coastguard Worker 	       void *arg)
809*7304104dSAndroid Build Coastguard Worker {
810*7304104dSAndroid Build Coastguard Worker   if (*(bool *) arg)
811*7304104dSAndroid Build Coastguard Worker     return DWARF_CB_ABORT;
812*7304104dSAndroid Build Coastguard Worker   *(bool *) arg = true;
813*7304104dSAndroid Build Coastguard Worker   return DWARF_CB_OK;
814*7304104dSAndroid Build Coastguard Worker }
815*7304104dSAndroid Build Coastguard Worker 
816*7304104dSAndroid Build Coastguard Worker struct process_dwflmod_args
817*7304104dSAndroid Build Coastguard Worker {
818*7304104dSAndroid Build Coastguard Worker   int fd;
819*7304104dSAndroid Build Coastguard Worker   bool only_one;
820*7304104dSAndroid Build Coastguard Worker };
821*7304104dSAndroid Build Coastguard Worker 
822*7304104dSAndroid Build Coastguard Worker static int
process_dwflmod(Dwfl_Module * dwflmod,void ** userdata,const char * name,Dwarf_Addr base,void * arg)823*7304104dSAndroid Build Coastguard Worker process_dwflmod (Dwfl_Module *dwflmod,
824*7304104dSAndroid Build Coastguard Worker 		 void **userdata __attribute__ ((unused)),
825*7304104dSAndroid Build Coastguard Worker 		 const char *name __attribute__ ((unused)),
826*7304104dSAndroid Build Coastguard Worker 		 Dwarf_Addr base __attribute__ ((unused)),
827*7304104dSAndroid Build Coastguard Worker 		 void *arg)
828*7304104dSAndroid Build Coastguard Worker {
829*7304104dSAndroid Build Coastguard Worker   const struct process_dwflmod_args *a = arg;
830*7304104dSAndroid Build Coastguard Worker 
831*7304104dSAndroid Build Coastguard Worker   /* Print the file name.  */
832*7304104dSAndroid Build Coastguard Worker   if (!a->only_one)
833*7304104dSAndroid Build Coastguard Worker     {
834*7304104dSAndroid Build Coastguard Worker       const char *fname;
835*7304104dSAndroid Build Coastguard Worker       dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
836*7304104dSAndroid Build Coastguard Worker 
837*7304104dSAndroid Build Coastguard Worker       printf ("\n%s:\n\n", fname);
838*7304104dSAndroid Build Coastguard Worker     }
839*7304104dSAndroid Build Coastguard Worker 
840*7304104dSAndroid Build Coastguard Worker   process_elf_file (dwflmod, a->fd);
841*7304104dSAndroid Build Coastguard Worker 
842*7304104dSAndroid Build Coastguard Worker   return DWARF_CB_OK;
843*7304104dSAndroid Build Coastguard Worker }
844*7304104dSAndroid Build Coastguard Worker 
845*7304104dSAndroid Build Coastguard Worker /* Stub libdwfl callback, only the ELF handle already open is ever used.
846*7304104dSAndroid Build Coastguard Worker    Only used for finding the alternate debug file if the Dwarf comes from
847*7304104dSAndroid Build Coastguard Worker    the main file.  We are not interested in separate debuginfo.  */
848*7304104dSAndroid Build Coastguard Worker static int
find_no_debuginfo(Dwfl_Module * mod,void ** userdata,const char * modname,Dwarf_Addr base,const char * file_name,const char * debuglink_file,GElf_Word debuglink_crc,char ** debuginfo_file_name)849*7304104dSAndroid Build Coastguard Worker find_no_debuginfo (Dwfl_Module *mod,
850*7304104dSAndroid Build Coastguard Worker 		   void **userdata,
851*7304104dSAndroid Build Coastguard Worker 		   const char *modname,
852*7304104dSAndroid Build Coastguard Worker 		   Dwarf_Addr base,
853*7304104dSAndroid Build Coastguard Worker 		   const char *file_name,
854*7304104dSAndroid Build Coastguard Worker 		   const char *debuglink_file,
855*7304104dSAndroid Build Coastguard Worker 		   GElf_Word debuglink_crc,
856*7304104dSAndroid Build Coastguard Worker 		   char **debuginfo_file_name)
857*7304104dSAndroid Build Coastguard Worker {
858*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr dwbias;
859*7304104dSAndroid Build Coastguard Worker   dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
860*7304104dSAndroid Build Coastguard Worker 
861*7304104dSAndroid Build Coastguard Worker   /* We are only interested if the Dwarf has been setup on the main
862*7304104dSAndroid Build Coastguard Worker      elf file but is only missing the alternate debug link.  If dwbias
863*7304104dSAndroid Build Coastguard Worker      hasn't even been setup, this is searching for separate debuginfo
864*7304104dSAndroid Build Coastguard Worker      for the main elf.  We don't care in that case.  */
865*7304104dSAndroid Build Coastguard Worker   if (dwbias == (Dwarf_Addr) -1)
866*7304104dSAndroid Build Coastguard Worker     return -1;
867*7304104dSAndroid Build Coastguard Worker 
868*7304104dSAndroid Build Coastguard Worker   return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
869*7304104dSAndroid Build Coastguard Worker 				       file_name, debuglink_file,
870*7304104dSAndroid Build Coastguard Worker 				       debuglink_crc, debuginfo_file_name);
871*7304104dSAndroid Build Coastguard Worker }
872*7304104dSAndroid Build Coastguard Worker 
873*7304104dSAndroid Build Coastguard Worker static Dwfl *
create_dwfl(int fd,const char * fname)874*7304104dSAndroid Build Coastguard Worker create_dwfl (int fd, const char *fname)
875*7304104dSAndroid Build Coastguard Worker {
876*7304104dSAndroid Build Coastguard Worker   /* Duplicate an fd for dwfl_report_offline to swallow.  */
877*7304104dSAndroid Build Coastguard Worker   int dwfl_fd = dup (fd);
878*7304104dSAndroid Build Coastguard Worker   if (unlikely (dwfl_fd < 0))
879*7304104dSAndroid Build Coastguard Worker     error_exit (errno, "dup");
880*7304104dSAndroid Build Coastguard Worker 
881*7304104dSAndroid Build Coastguard Worker   /* Use libdwfl in a trivial way to open the libdw handle for us.
882*7304104dSAndroid Build Coastguard Worker      This takes care of applying relocations to DWARF data in ET_REL files.  */
883*7304104dSAndroid Build Coastguard Worker   static const Dwfl_Callbacks callbacks =
884*7304104dSAndroid Build Coastguard Worker     {
885*7304104dSAndroid Build Coastguard Worker       .section_address = dwfl_offline_section_address,
886*7304104dSAndroid Build Coastguard Worker       .find_debuginfo = find_no_debuginfo
887*7304104dSAndroid Build Coastguard Worker     };
888*7304104dSAndroid Build Coastguard Worker   Dwfl *dwfl = dwfl_begin (&callbacks);
889*7304104dSAndroid Build Coastguard Worker   if (likely (dwfl != NULL))
890*7304104dSAndroid Build Coastguard Worker     /* Let 0 be the logical address of the file (or first in archive).  */
891*7304104dSAndroid Build Coastguard Worker     dwfl->offline_next_address = 0;
892*7304104dSAndroid Build Coastguard Worker   if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
893*7304104dSAndroid Build Coastguard Worker     {
894*7304104dSAndroid Build Coastguard Worker       struct stat st;
895*7304104dSAndroid Build Coastguard Worker       if (fstat (dwfl_fd, &st) != 0)
896*7304104dSAndroid Build Coastguard Worker 	error (0, errno, _("cannot stat input file"));
897*7304104dSAndroid Build Coastguard Worker       else if (unlikely (st.st_size == 0))
898*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("input file is empty"));
899*7304104dSAndroid Build Coastguard Worker       else
900*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("failed reading '%s': %s"),
901*7304104dSAndroid Build Coastguard Worker 	       fname, dwfl_errmsg (-1));
902*7304104dSAndroid Build Coastguard Worker       close (dwfl_fd);		/* Consumed on success, not on failure.  */
903*7304104dSAndroid Build Coastguard Worker       dwfl = NULL;
904*7304104dSAndroid Build Coastguard Worker     }
905*7304104dSAndroid Build Coastguard Worker   else
906*7304104dSAndroid Build Coastguard Worker     dwfl_report_end (dwfl, NULL, NULL);
907*7304104dSAndroid Build Coastguard Worker 
908*7304104dSAndroid Build Coastguard Worker   return dwfl;
909*7304104dSAndroid Build Coastguard Worker }
910*7304104dSAndroid Build Coastguard Worker 
911*7304104dSAndroid Build Coastguard Worker /* Process one input file.  */
912*7304104dSAndroid Build Coastguard Worker static void
process_file(int fd,const char * fname,bool only_one)913*7304104dSAndroid Build Coastguard Worker process_file (int fd, const char *fname, bool only_one)
914*7304104dSAndroid Build Coastguard Worker {
915*7304104dSAndroid Build Coastguard Worker   if (print_archive_index)
916*7304104dSAndroid Build Coastguard Worker     check_archive_index (fd, fname, only_one);
917*7304104dSAndroid Build Coastguard Worker 
918*7304104dSAndroid Build Coastguard Worker   if (!any_control_option)
919*7304104dSAndroid Build Coastguard Worker     return;
920*7304104dSAndroid Build Coastguard Worker 
921*7304104dSAndroid Build Coastguard Worker   if (elf_input_section != NULL)
922*7304104dSAndroid Build Coastguard Worker     {
923*7304104dSAndroid Build Coastguard Worker       /* Replace fname and fd with section content. */
924*7304104dSAndroid Build Coastguard Worker       char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
925*7304104dSAndroid Build Coastguard Worker       sprintf (fnname, "%s:%s", fname, elf_input_section);
926*7304104dSAndroid Build Coastguard Worker       fd = open_input_section (fd);
927*7304104dSAndroid Build Coastguard Worker       if (fd == -1)
928*7304104dSAndroid Build Coastguard Worker         {
929*7304104dSAndroid Build Coastguard Worker           error (0, 0, _("No such section '%s' in '%s'"),
930*7304104dSAndroid Build Coastguard Worker 		 elf_input_section, fname);
931*7304104dSAndroid Build Coastguard Worker           return;
932*7304104dSAndroid Build Coastguard Worker         }
933*7304104dSAndroid Build Coastguard Worker       fname = fnname;
934*7304104dSAndroid Build Coastguard Worker     }
935*7304104dSAndroid Build Coastguard Worker 
936*7304104dSAndroid Build Coastguard Worker   Dwfl *dwfl = create_dwfl (fd, fname);
937*7304104dSAndroid Build Coastguard Worker   if (dwfl != NULL)
938*7304104dSAndroid Build Coastguard Worker     {
939*7304104dSAndroid Build Coastguard Worker       if (only_one)
940*7304104dSAndroid Build Coastguard Worker 	{
941*7304104dSAndroid Build Coastguard Worker 	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
942*7304104dSAndroid Build Coastguard Worker 	  bool seen = false;
943*7304104dSAndroid Build Coastguard Worker 	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
944*7304104dSAndroid Build Coastguard Worker 	}
945*7304104dSAndroid Build Coastguard Worker 
946*7304104dSAndroid Build Coastguard Worker       /* Process the one or more modules gleaned from this file.  */
947*7304104dSAndroid Build Coastguard Worker       struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
948*7304104dSAndroid Build Coastguard Worker       dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
949*7304104dSAndroid Build Coastguard Worker     }
950*7304104dSAndroid Build Coastguard Worker   /* Terrible hack for hooking unrelated skeleton/split compile units,
951*7304104dSAndroid Build Coastguard Worker      see __libdw_link_skel_split in print_debug.  */
952*7304104dSAndroid Build Coastguard Worker   if (! do_not_close_dwfl)
953*7304104dSAndroid Build Coastguard Worker     dwfl_end (dwfl);
954*7304104dSAndroid Build Coastguard Worker 
955*7304104dSAndroid Build Coastguard Worker   /* Need to close the replaced fd if we created it.  Caller takes
956*7304104dSAndroid Build Coastguard Worker      care of original.  */
957*7304104dSAndroid Build Coastguard Worker   if (elf_input_section != NULL)
958*7304104dSAndroid Build Coastguard Worker     close (fd);
959*7304104dSAndroid Build Coastguard Worker }
960*7304104dSAndroid Build Coastguard Worker 
961*7304104dSAndroid Build Coastguard Worker /* Check whether there are any compressed sections in the ELF file.  */
962*7304104dSAndroid Build Coastguard Worker static bool
elf_contains_chdrs(Elf * elf)963*7304104dSAndroid Build Coastguard Worker elf_contains_chdrs (Elf *elf)
964*7304104dSAndroid Build Coastguard Worker {
965*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
966*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (elf, scn)) != NULL)
967*7304104dSAndroid Build Coastguard Worker     {
968*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
969*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
970*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
971*7304104dSAndroid Build Coastguard Worker 	return true;
972*7304104dSAndroid Build Coastguard Worker     }
973*7304104dSAndroid Build Coastguard Worker   return false;
974*7304104dSAndroid Build Coastguard Worker }
975*7304104dSAndroid Build Coastguard Worker 
976*7304104dSAndroid Build Coastguard Worker /* Process one ELF file.  */
977*7304104dSAndroid Build Coastguard Worker static void
process_elf_file(Dwfl_Module * dwflmod,int fd)978*7304104dSAndroid Build Coastguard Worker process_elf_file (Dwfl_Module *dwflmod, int fd)
979*7304104dSAndroid Build Coastguard Worker {
980*7304104dSAndroid Build Coastguard Worker   GElf_Addr dwflbias;
981*7304104dSAndroid Build Coastguard Worker   Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
982*7304104dSAndroid Build Coastguard Worker 
983*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr ehdr_mem;
984*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
985*7304104dSAndroid Build Coastguard Worker 
986*7304104dSAndroid Build Coastguard Worker   if (ehdr == NULL)
987*7304104dSAndroid Build Coastguard Worker     {
988*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot read ELF header: %s"), elf_errmsg (-1));
989*7304104dSAndroid Build Coastguard Worker       return;
990*7304104dSAndroid Build Coastguard Worker     }
991*7304104dSAndroid Build Coastguard Worker 
992*7304104dSAndroid Build Coastguard Worker   Ebl *ebl = ebl_openbackend (elf);
993*7304104dSAndroid Build Coastguard Worker   if (unlikely (ebl == NULL))
994*7304104dSAndroid Build Coastguard Worker     {
995*7304104dSAndroid Build Coastguard Worker     ebl_error:
996*7304104dSAndroid Build Coastguard Worker       error (0, errno, _("cannot create EBL handle"));
997*7304104dSAndroid Build Coastguard Worker       return;
998*7304104dSAndroid Build Coastguard Worker     }
999*7304104dSAndroid Build Coastguard Worker 
1000*7304104dSAndroid Build Coastguard Worker   /* Determine the number of sections.  */
1001*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
1002*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot determine number of sections: %s"),
1003*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1004*7304104dSAndroid Build Coastguard Worker 
1005*7304104dSAndroid Build Coastguard Worker   /* Determine the number of phdrs.  */
1006*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
1007*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot determine number of program headers: %s"),
1008*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1009*7304104dSAndroid Build Coastguard Worker 
1010*7304104dSAndroid Build Coastguard Worker   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
1011*7304104dSAndroid Build Coastguard Worker      may have applied relocation to some sections.  If there are any
1012*7304104dSAndroid Build Coastguard Worker      compressed sections, any pass (or libdw/libdwfl) might have
1013*7304104dSAndroid Build Coastguard Worker      uncompressed them.  So we need to get a fresh Elf handle on the
1014*7304104dSAndroid Build Coastguard Worker      file to display those.  */
1015*7304104dSAndroid Build Coastguard Worker   bool print_unchanged = ((print_section_header
1016*7304104dSAndroid Build Coastguard Worker 			   || print_relocations
1017*7304104dSAndroid Build Coastguard Worker 			   || dump_data_sections != NULL
1018*7304104dSAndroid Build Coastguard Worker 			   || print_notes)
1019*7304104dSAndroid Build Coastguard Worker 			  && (ehdr->e_type == ET_REL
1020*7304104dSAndroid Build Coastguard Worker 			      || elf_contains_chdrs (ebl->elf)));
1021*7304104dSAndroid Build Coastguard Worker 
1022*7304104dSAndroid Build Coastguard Worker   Elf *pure_elf = NULL;
1023*7304104dSAndroid Build Coastguard Worker   Ebl *pure_ebl = ebl;
1024*7304104dSAndroid Build Coastguard Worker   if (print_unchanged)
1025*7304104dSAndroid Build Coastguard Worker     {
1026*7304104dSAndroid Build Coastguard Worker       /* Read the file afresh.  */
1027*7304104dSAndroid Build Coastguard Worker       off_t aroff = elf_getaroff (elf);
1028*7304104dSAndroid Build Coastguard Worker       pure_elf = dwelf_elf_begin (fd);
1029*7304104dSAndroid Build Coastguard Worker       if (aroff > 0)
1030*7304104dSAndroid Build Coastguard Worker 	{
1031*7304104dSAndroid Build Coastguard Worker 	  /* Archive member.  */
1032*7304104dSAndroid Build Coastguard Worker 	  (void) elf_rand (pure_elf, aroff);
1033*7304104dSAndroid Build Coastguard Worker 	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
1034*7304104dSAndroid Build Coastguard Worker 	  elf_end (pure_elf);
1035*7304104dSAndroid Build Coastguard Worker 	  pure_elf = armem;
1036*7304104dSAndroid Build Coastguard Worker 	}
1037*7304104dSAndroid Build Coastguard Worker       if (pure_elf == NULL)
1038*7304104dSAndroid Build Coastguard Worker 	{
1039*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot read ELF: %s"), elf_errmsg (-1));
1040*7304104dSAndroid Build Coastguard Worker 	  return;
1041*7304104dSAndroid Build Coastguard Worker 	}
1042*7304104dSAndroid Build Coastguard Worker       pure_ebl = ebl_openbackend (pure_elf);
1043*7304104dSAndroid Build Coastguard Worker       if (pure_ebl == NULL)
1044*7304104dSAndroid Build Coastguard Worker 	goto ebl_error;
1045*7304104dSAndroid Build Coastguard Worker     }
1046*7304104dSAndroid Build Coastguard Worker 
1047*7304104dSAndroid Build Coastguard Worker   bool symtab_printed = false;
1048*7304104dSAndroid Build Coastguard Worker 
1049*7304104dSAndroid Build Coastguard Worker   if (print_file_header)
1050*7304104dSAndroid Build Coastguard Worker     print_ehdr (ebl, ehdr);
1051*7304104dSAndroid Build Coastguard Worker   if (print_section_header)
1052*7304104dSAndroid Build Coastguard Worker     print_shdr (pure_ebl, ehdr);
1053*7304104dSAndroid Build Coastguard Worker   if (print_program_header)
1054*7304104dSAndroid Build Coastguard Worker     print_phdr (ebl, ehdr);
1055*7304104dSAndroid Build Coastguard Worker   if (print_section_groups)
1056*7304104dSAndroid Build Coastguard Worker     print_scngrp (ebl);
1057*7304104dSAndroid Build Coastguard Worker   if (print_dynamic_table)
1058*7304104dSAndroid Build Coastguard Worker     print_dynamic (ebl);
1059*7304104dSAndroid Build Coastguard Worker   if (print_relocations)
1060*7304104dSAndroid Build Coastguard Worker     print_relocs (pure_ebl, dwflmod, ehdr);
1061*7304104dSAndroid Build Coastguard Worker   if (print_histogram)
1062*7304104dSAndroid Build Coastguard Worker     handle_hash (ebl);
1063*7304104dSAndroid Build Coastguard Worker   if (print_symbol_table || print_dynsym_table)
1064*7304104dSAndroid Build Coastguard Worker     symtab_printed |= print_symtab (ebl, SHT_DYNSYM);
1065*7304104dSAndroid Build Coastguard Worker   if (print_version_info)
1066*7304104dSAndroid Build Coastguard Worker     print_verinfo (ebl);
1067*7304104dSAndroid Build Coastguard Worker   if (print_symbol_table && !use_dynamic_segment)
1068*7304104dSAndroid Build Coastguard Worker     symtab_printed |= print_symtab (ebl, SHT_SYMTAB);
1069*7304104dSAndroid Build Coastguard Worker 
1070*7304104dSAndroid Build Coastguard Worker   if ((print_symbol_table || print_dynsym_table)
1071*7304104dSAndroid Build Coastguard Worker       && !symtab_printed && symbol_table_section != NULL)
1072*7304104dSAndroid Build Coastguard Worker     printf ("WARNING: %s: '%s'\n", _("cannot find section"),
1073*7304104dSAndroid Build Coastguard Worker         symbol_table_section);
1074*7304104dSAndroid Build Coastguard Worker 
1075*7304104dSAndroid Build Coastguard Worker   if (print_arch)
1076*7304104dSAndroid Build Coastguard Worker     print_liblist (ebl);
1077*7304104dSAndroid Build Coastguard Worker   if (print_arch)
1078*7304104dSAndroid Build Coastguard Worker     print_attributes (ebl, ehdr);
1079*7304104dSAndroid Build Coastguard Worker   if (dump_data_sections != NULL)
1080*7304104dSAndroid Build Coastguard Worker     dump_data (pure_ebl);
1081*7304104dSAndroid Build Coastguard Worker   if (string_sections != NULL)
1082*7304104dSAndroid Build Coastguard Worker     dump_strings (ebl);
1083*7304104dSAndroid Build Coastguard Worker   if ((print_debug_sections | implicit_debug_sections) != 0)
1084*7304104dSAndroid Build Coastguard Worker     print_debug (dwflmod, ebl, ehdr);
1085*7304104dSAndroid Build Coastguard Worker   if (print_notes)
1086*7304104dSAndroid Build Coastguard Worker     handle_notes (pure_ebl, ehdr);
1087*7304104dSAndroid Build Coastguard Worker   if (print_string_sections)
1088*7304104dSAndroid Build Coastguard Worker     print_strings (ebl);
1089*7304104dSAndroid Build Coastguard Worker 
1090*7304104dSAndroid Build Coastguard Worker   if (pure_ebl != ebl)
1091*7304104dSAndroid Build Coastguard Worker     {
1092*7304104dSAndroid Build Coastguard Worker       ebl_closebackend (ebl);
1093*7304104dSAndroid Build Coastguard Worker       ebl_closebackend (pure_ebl);
1094*7304104dSAndroid Build Coastguard Worker       elf_end (pure_elf);
1095*7304104dSAndroid Build Coastguard Worker     }
1096*7304104dSAndroid Build Coastguard Worker   else
1097*7304104dSAndroid Build Coastguard Worker     ebl_closebackend (ebl);
1098*7304104dSAndroid Build Coastguard Worker }
1099*7304104dSAndroid Build Coastguard Worker 
1100*7304104dSAndroid Build Coastguard Worker 
1101*7304104dSAndroid Build Coastguard Worker /* Print file type.  */
1102*7304104dSAndroid Build Coastguard Worker static void
print_file_type(unsigned short int e_type)1103*7304104dSAndroid Build Coastguard Worker print_file_type (unsigned short int e_type)
1104*7304104dSAndroid Build Coastguard Worker {
1105*7304104dSAndroid Build Coastguard Worker   if (likely (e_type <= ET_CORE))
1106*7304104dSAndroid Build Coastguard Worker     {
1107*7304104dSAndroid Build Coastguard Worker       static const char *const knowntypes[] =
1108*7304104dSAndroid Build Coastguard Worker       {
1109*7304104dSAndroid Build Coastguard Worker 	N_("NONE (None)"),
1110*7304104dSAndroid Build Coastguard Worker 	N_("REL (Relocatable file)"),
1111*7304104dSAndroid Build Coastguard Worker 	N_("EXEC (Executable file)"),
1112*7304104dSAndroid Build Coastguard Worker 	N_("DYN (Shared object file)"),
1113*7304104dSAndroid Build Coastguard Worker 	N_("CORE (Core file)")
1114*7304104dSAndroid Build Coastguard Worker       };
1115*7304104dSAndroid Build Coastguard Worker       puts (_(knowntypes[e_type]));
1116*7304104dSAndroid Build Coastguard Worker     }
1117*7304104dSAndroid Build Coastguard Worker   else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
1118*7304104dSAndroid Build Coastguard Worker     printf (_("OS Specific: (%x)\n"),  e_type);
1119*7304104dSAndroid Build Coastguard Worker   else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
1120*7304104dSAndroid Build Coastguard Worker     printf (_("Processor Specific: (%x)\n"),  e_type);
1121*7304104dSAndroid Build Coastguard Worker   else
1122*7304104dSAndroid Build Coastguard Worker     puts ("???");
1123*7304104dSAndroid Build Coastguard Worker }
1124*7304104dSAndroid Build Coastguard Worker 
1125*7304104dSAndroid Build Coastguard Worker 
1126*7304104dSAndroid Build Coastguard Worker /* Print ELF header.  */
1127*7304104dSAndroid Build Coastguard Worker static void
print_ehdr(Ebl * ebl,GElf_Ehdr * ehdr)1128*7304104dSAndroid Build Coastguard Worker print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
1129*7304104dSAndroid Build Coastguard Worker {
1130*7304104dSAndroid Build Coastguard Worker   fputs_unlocked (_("ELF Header:\n  Magic:  "), stdout);
1131*7304104dSAndroid Build Coastguard Worker   for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
1132*7304104dSAndroid Build Coastguard Worker     printf (" %02hhx", ehdr->e_ident[cnt]);
1133*7304104dSAndroid Build Coastguard Worker 
1134*7304104dSAndroid Build Coastguard Worker   printf (_("\n  Class:                             %s\n"),
1135*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
1136*7304104dSAndroid Build Coastguard Worker 	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
1137*7304104dSAndroid Build Coastguard Worker 	  : "\?\?\?");
1138*7304104dSAndroid Build Coastguard Worker 
1139*7304104dSAndroid Build Coastguard Worker   printf (_("  Data:                              %s\n"),
1140*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
1141*7304104dSAndroid Build Coastguard Worker 	  ? "2's complement, little endian"
1142*7304104dSAndroid Build Coastguard Worker 	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
1143*7304104dSAndroid Build Coastguard Worker 	  ? "2's complement, big endian" : "\?\?\?");
1144*7304104dSAndroid Build Coastguard Worker 
1145*7304104dSAndroid Build Coastguard Worker   printf (_("  Ident Version:                     %hhd %s\n"),
1146*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_ident[EI_VERSION],
1147*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? _("(current)")
1148*7304104dSAndroid Build Coastguard Worker 	  : "(\?\?\?)");
1149*7304104dSAndroid Build Coastguard Worker 
1150*7304104dSAndroid Build Coastguard Worker   char buf[512];
1151*7304104dSAndroid Build Coastguard Worker   printf (_("  OS/ABI:                            %s\n"),
1152*7304104dSAndroid Build Coastguard Worker 	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
1153*7304104dSAndroid Build Coastguard Worker 
1154*7304104dSAndroid Build Coastguard Worker   printf (_("  ABI Version:                       %hhd\n"),
1155*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_ident[EI_ABIVERSION]);
1156*7304104dSAndroid Build Coastguard Worker 
1157*7304104dSAndroid Build Coastguard Worker   fputs_unlocked (_("  Type:                              "), stdout);
1158*7304104dSAndroid Build Coastguard Worker   print_file_type (ehdr->e_type);
1159*7304104dSAndroid Build Coastguard Worker 
1160*7304104dSAndroid Build Coastguard Worker   const char *machine = dwelf_elf_e_machine_string (ehdr->e_machine);
1161*7304104dSAndroid Build Coastguard Worker   if (machine != NULL)
1162*7304104dSAndroid Build Coastguard Worker     printf (_("  Machine:                           %s\n"), machine);
1163*7304104dSAndroid Build Coastguard Worker   else
1164*7304104dSAndroid Build Coastguard Worker     printf (_("  Machine:                           <unknown>: 0x%x\n"),
1165*7304104dSAndroid Build Coastguard Worker 	    ehdr->e_machine);
1166*7304104dSAndroid Build Coastguard Worker 
1167*7304104dSAndroid Build Coastguard Worker   printf (_("  Version:                           %d %s\n"),
1168*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_version,
1169*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_version  == EV_CURRENT ? _("(current)") : "(\?\?\?)");
1170*7304104dSAndroid Build Coastguard Worker 
1171*7304104dSAndroid Build Coastguard Worker   printf (_("  Entry point address:               %#" PRIx64 "\n"),
1172*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_entry);
1173*7304104dSAndroid Build Coastguard Worker 
1174*7304104dSAndroid Build Coastguard Worker   printf (_("  Start of program headers:          %" PRId64 " %s\n"),
1175*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_phoff, _("(bytes into file)"));
1176*7304104dSAndroid Build Coastguard Worker 
1177*7304104dSAndroid Build Coastguard Worker   printf (_("  Start of section headers:          %" PRId64 " %s\n"),
1178*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_shoff, _("(bytes into file)"));
1179*7304104dSAndroid Build Coastguard Worker 
1180*7304104dSAndroid Build Coastguard Worker   printf (_("  Flags:                             %s\n"),
1181*7304104dSAndroid Build Coastguard Worker 	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
1182*7304104dSAndroid Build Coastguard Worker 
1183*7304104dSAndroid Build Coastguard Worker   printf (_("  Size of this header:               %" PRId16 " %s\n"),
1184*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_ehsize, _("(bytes)"));
1185*7304104dSAndroid Build Coastguard Worker 
1186*7304104dSAndroid Build Coastguard Worker   printf (_("  Size of program header entries:    %" PRId16 " %s\n"),
1187*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_phentsize, _("(bytes)"));
1188*7304104dSAndroid Build Coastguard Worker 
1189*7304104dSAndroid Build Coastguard Worker   printf (_("  Number of program headers entries: %" PRId16),
1190*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_phnum);
1191*7304104dSAndroid Build Coastguard Worker   if (ehdr->e_phnum == PN_XNUM)
1192*7304104dSAndroid Build Coastguard Worker     {
1193*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1194*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1195*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL)
1196*7304104dSAndroid Build Coastguard Worker 	printf (_(" (%" PRIu32 " in [0].sh_info)"),
1197*7304104dSAndroid Build Coastguard Worker 		(uint32_t) shdr->sh_info);
1198*7304104dSAndroid Build Coastguard Worker       else
1199*7304104dSAndroid Build Coastguard Worker 	fputs_unlocked (_(" ([0] not available)"), stdout);
1200*7304104dSAndroid Build Coastguard Worker     }
1201*7304104dSAndroid Build Coastguard Worker   fputc_unlocked ('\n', stdout);
1202*7304104dSAndroid Build Coastguard Worker 
1203*7304104dSAndroid Build Coastguard Worker   printf (_("  Size of section header entries:    %" PRId16 " %s\n"),
1204*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_shentsize, _("(bytes)"));
1205*7304104dSAndroid Build Coastguard Worker 
1206*7304104dSAndroid Build Coastguard Worker   printf (_("  Number of section headers entries: %" PRId16),
1207*7304104dSAndroid Build Coastguard Worker 	  ehdr->e_shnum);
1208*7304104dSAndroid Build Coastguard Worker   if (ehdr->e_shnum == 0)
1209*7304104dSAndroid Build Coastguard Worker     {
1210*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1211*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1212*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL)
1213*7304104dSAndroid Build Coastguard Worker 	printf (_(" (%" PRIu32 " in [0].sh_size)"),
1214*7304104dSAndroid Build Coastguard Worker 		(uint32_t) shdr->sh_size);
1215*7304104dSAndroid Build Coastguard Worker       else
1216*7304104dSAndroid Build Coastguard Worker 	fputs_unlocked (_(" ([0] not available)"), stdout);
1217*7304104dSAndroid Build Coastguard Worker     }
1218*7304104dSAndroid Build Coastguard Worker   fputc_unlocked ('\n', stdout);
1219*7304104dSAndroid Build Coastguard Worker 
1220*7304104dSAndroid Build Coastguard Worker   if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
1221*7304104dSAndroid Build Coastguard Worker     {
1222*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1223*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
1224*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL)
1225*7304104dSAndroid Build Coastguard Worker 	/* We managed to get the zeroth section.  */
1226*7304104dSAndroid Build Coastguard Worker 	snprintf (buf, sizeof (buf), _(" (%" PRIu32 " in [0].sh_link)"),
1227*7304104dSAndroid Build Coastguard Worker 		  (uint32_t) shdr->sh_link);
1228*7304104dSAndroid Build Coastguard Worker       else
1229*7304104dSAndroid Build Coastguard Worker 	{
1230*7304104dSAndroid Build Coastguard Worker 	  strncpy (buf, _(" ([0] not available)"), sizeof (buf) - 1);
1231*7304104dSAndroid Build Coastguard Worker 	  buf[sizeof (buf) - 1] = '\0';
1232*7304104dSAndroid Build Coastguard Worker 	}
1233*7304104dSAndroid Build Coastguard Worker 
1234*7304104dSAndroid Build Coastguard Worker       printf (_("  Section header string table index: XINDEX%s\n\n"),
1235*7304104dSAndroid Build Coastguard Worker 	      buf);
1236*7304104dSAndroid Build Coastguard Worker     }
1237*7304104dSAndroid Build Coastguard Worker   else
1238*7304104dSAndroid Build Coastguard Worker     printf (_("  Section header string table index: %" PRId16 "\n\n"),
1239*7304104dSAndroid Build Coastguard Worker 	    ehdr->e_shstrndx);
1240*7304104dSAndroid Build Coastguard Worker }
1241*7304104dSAndroid Build Coastguard Worker 
1242*7304104dSAndroid Build Coastguard Worker 
1243*7304104dSAndroid Build Coastguard Worker static const char *
get_visibility_type(int value)1244*7304104dSAndroid Build Coastguard Worker get_visibility_type (int value)
1245*7304104dSAndroid Build Coastguard Worker {
1246*7304104dSAndroid Build Coastguard Worker   switch (value)
1247*7304104dSAndroid Build Coastguard Worker     {
1248*7304104dSAndroid Build Coastguard Worker     case STV_DEFAULT:
1249*7304104dSAndroid Build Coastguard Worker       return "DEFAULT";
1250*7304104dSAndroid Build Coastguard Worker     case STV_INTERNAL:
1251*7304104dSAndroid Build Coastguard Worker       return "INTERNAL";
1252*7304104dSAndroid Build Coastguard Worker     case STV_HIDDEN:
1253*7304104dSAndroid Build Coastguard Worker       return "HIDDEN";
1254*7304104dSAndroid Build Coastguard Worker     case STV_PROTECTED:
1255*7304104dSAndroid Build Coastguard Worker       return "PROTECTED";
1256*7304104dSAndroid Build Coastguard Worker     default:
1257*7304104dSAndroid Build Coastguard Worker       return "???";
1258*7304104dSAndroid Build Coastguard Worker     }
1259*7304104dSAndroid Build Coastguard Worker }
1260*7304104dSAndroid Build Coastguard Worker 
1261*7304104dSAndroid Build Coastguard Worker static const char *
elf_ch_type_name(unsigned int code)1262*7304104dSAndroid Build Coastguard Worker elf_ch_type_name (unsigned int code)
1263*7304104dSAndroid Build Coastguard Worker {
1264*7304104dSAndroid Build Coastguard Worker   switch (code)
1265*7304104dSAndroid Build Coastguard Worker     {
1266*7304104dSAndroid Build Coastguard Worker     case 0:
1267*7304104dSAndroid Build Coastguard Worker       return "NONE";
1268*7304104dSAndroid Build Coastguard Worker     case ELFCOMPRESS_ZLIB:
1269*7304104dSAndroid Build Coastguard Worker       return "ZLIB";
1270*7304104dSAndroid Build Coastguard Worker     case ELFCOMPRESS_ZSTD:
1271*7304104dSAndroid Build Coastguard Worker       return "ZSTD";
1272*7304104dSAndroid Build Coastguard Worker     default:
1273*7304104dSAndroid Build Coastguard Worker       return "UNKNOWN";
1274*7304104dSAndroid Build Coastguard Worker     }
1275*7304104dSAndroid Build Coastguard Worker }
1276*7304104dSAndroid Build Coastguard Worker 
1277*7304104dSAndroid Build Coastguard Worker /* Print the section headers.  */
1278*7304104dSAndroid Build Coastguard Worker static void
print_shdr(Ebl * ebl,GElf_Ehdr * ehdr)1279*7304104dSAndroid Build Coastguard Worker print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
1280*7304104dSAndroid Build Coastguard Worker {
1281*7304104dSAndroid Build Coastguard Worker   size_t cnt;
1282*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
1283*7304104dSAndroid Build Coastguard Worker 
1284*7304104dSAndroid Build Coastguard Worker   if (! print_file_header)
1285*7304104dSAndroid Build Coastguard Worker     {
1286*7304104dSAndroid Build Coastguard Worker       size_t sections;
1287*7304104dSAndroid Build Coastguard Worker       if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
1288*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get number of sections: %s"),
1289*7304104dSAndroid Build Coastguard Worker 		    elf_errmsg (-1));
1290*7304104dSAndroid Build Coastguard Worker 
1291*7304104dSAndroid Build Coastguard Worker       printf (_("\
1292*7304104dSAndroid Build Coastguard Worker There are %zd section headers, starting at offset %#" PRIx64 ":\n\
1293*7304104dSAndroid Build Coastguard Worker \n"),
1294*7304104dSAndroid Build Coastguard Worker 	      sections, ehdr->e_shoff);
1295*7304104dSAndroid Build Coastguard Worker     }
1296*7304104dSAndroid Build Coastguard Worker 
1297*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
1298*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1299*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index: %s"),
1300*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1301*7304104dSAndroid Build Coastguard Worker 
1302*7304104dSAndroid Build Coastguard Worker   puts (_("Section Headers:"));
1303*7304104dSAndroid Build Coastguard Worker 
1304*7304104dSAndroid Build Coastguard Worker   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1305*7304104dSAndroid Build Coastguard Worker     puts (_("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
1306*7304104dSAndroid Build Coastguard Worker   else
1307*7304104dSAndroid Build Coastguard Worker     puts (_("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
1308*7304104dSAndroid Build Coastguard Worker 
1309*7304104dSAndroid Build Coastguard Worker   if (print_decompress)
1310*7304104dSAndroid Build Coastguard Worker     {
1311*7304104dSAndroid Build Coastguard Worker       if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1312*7304104dSAndroid Build Coastguard Worker 	puts (_("     [Compression  Size   Al]"));
1313*7304104dSAndroid Build Coastguard Worker       else
1314*7304104dSAndroid Build Coastguard Worker 	puts (_("     [Compression  Size     Al]"));
1315*7304104dSAndroid Build Coastguard Worker     }
1316*7304104dSAndroid Build Coastguard Worker 
1317*7304104dSAndroid Build Coastguard Worker   for (cnt = 0; cnt < shnum; ++cnt)
1318*7304104dSAndroid Build Coastguard Worker     {
1319*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
1320*7304104dSAndroid Build Coastguard Worker 
1321*7304104dSAndroid Build Coastguard Worker       if (unlikely (scn == NULL))
1322*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get section: %s"),
1323*7304104dSAndroid Build Coastguard Worker 		    elf_errmsg (-1));
1324*7304104dSAndroid Build Coastguard Worker 
1325*7304104dSAndroid Build Coastguard Worker       /* Get the section header.  */
1326*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1327*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1328*7304104dSAndroid Build Coastguard Worker       if (unlikely (shdr == NULL))
1329*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get section header: %s"),
1330*7304104dSAndroid Build Coastguard Worker 		    elf_errmsg (-1));
1331*7304104dSAndroid Build Coastguard Worker 
1332*7304104dSAndroid Build Coastguard Worker       char flagbuf[20];
1333*7304104dSAndroid Build Coastguard Worker       char *cp = flagbuf;
1334*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_WRITE)
1335*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'W';
1336*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_ALLOC)
1337*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'A';
1338*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_EXECINSTR)
1339*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'X';
1340*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_MERGE)
1341*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'M';
1342*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_STRINGS)
1343*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'S';
1344*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_INFO_LINK)
1345*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'I';
1346*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_LINK_ORDER)
1347*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'L';
1348*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_OS_NONCONFORMING)
1349*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'N';
1350*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_GROUP)
1351*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'G';
1352*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_TLS)
1353*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'T';
1354*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_COMPRESSED)
1355*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'C';
1356*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_ORDERED)
1357*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'O';
1358*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_EXCLUDE)
1359*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'E';
1360*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_flags & SHF_GNU_RETAIN)
1361*7304104dSAndroid Build Coastguard Worker 	*cp++ = 'R';
1362*7304104dSAndroid Build Coastguard Worker       *cp = '\0';
1363*7304104dSAndroid Build Coastguard Worker 
1364*7304104dSAndroid Build Coastguard Worker       const char *sname;
1365*7304104dSAndroid Build Coastguard Worker       char buf[128];
1366*7304104dSAndroid Build Coastguard Worker       sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
1367*7304104dSAndroid Build Coastguard Worker       printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
1368*7304104dSAndroid Build Coastguard Worker 	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
1369*7304104dSAndroid Build Coastguard Worker 	      " %2" PRId64 "\n",
1370*7304104dSAndroid Build Coastguard Worker 	      cnt, sname,
1371*7304104dSAndroid Build Coastguard Worker 	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
1372*7304104dSAndroid Build Coastguard Worker 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
1373*7304104dSAndroid Build Coastguard Worker 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
1374*7304104dSAndroid Build Coastguard Worker 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
1375*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
1376*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_addralign);
1377*7304104dSAndroid Build Coastguard Worker 
1378*7304104dSAndroid Build Coastguard Worker       if (print_decompress)
1379*7304104dSAndroid Build Coastguard Worker 	{
1380*7304104dSAndroid Build Coastguard Worker 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1381*7304104dSAndroid Build Coastguard Worker 	    {
1382*7304104dSAndroid Build Coastguard Worker 	      GElf_Chdr chdr;
1383*7304104dSAndroid Build Coastguard Worker 	      if (gelf_getchdr (scn, &chdr) != NULL)
1384*7304104dSAndroid Build Coastguard Worker 		printf ("     [ELF %s (%" PRId32 ") %0*" PRIx64
1385*7304104dSAndroid Build Coastguard Worker 			" %2" PRId64 "]\n",
1386*7304104dSAndroid Build Coastguard Worker 			elf_ch_type_name (chdr.ch_type),
1387*7304104dSAndroid Build Coastguard Worker 			chdr.ch_type,
1388*7304104dSAndroid Build Coastguard Worker 			ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
1389*7304104dSAndroid Build Coastguard Worker 			chdr.ch_size, chdr.ch_addralign);
1390*7304104dSAndroid Build Coastguard Worker 	      else
1391*7304104dSAndroid Build Coastguard Worker 		error (0, 0,
1392*7304104dSAndroid Build Coastguard Worker 		       _("bad compression header for section %zd: %s"),
1393*7304104dSAndroid Build Coastguard Worker 		       elf_ndxscn (scn), elf_errmsg (-1));
1394*7304104dSAndroid Build Coastguard Worker 	    }
1395*7304104dSAndroid Build Coastguard Worker 	  else if (startswith (sname, ".zdebug"))
1396*7304104dSAndroid Build Coastguard Worker 	    {
1397*7304104dSAndroid Build Coastguard Worker 	      ssize_t size;
1398*7304104dSAndroid Build Coastguard Worker 	      if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
1399*7304104dSAndroid Build Coastguard Worker 		printf ("     [GNU ZLIB     %0*zx   ]\n",
1400*7304104dSAndroid Build Coastguard Worker 			ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
1401*7304104dSAndroid Build Coastguard Worker 	      else
1402*7304104dSAndroid Build Coastguard Worker 		error (0, 0,
1403*7304104dSAndroid Build Coastguard Worker 		       _("bad gnu compressed size for section %zd: %s"),
1404*7304104dSAndroid Build Coastguard Worker 		       elf_ndxscn (scn), elf_errmsg (-1));
1405*7304104dSAndroid Build Coastguard Worker 	    }
1406*7304104dSAndroid Build Coastguard Worker 	}
1407*7304104dSAndroid Build Coastguard Worker     }
1408*7304104dSAndroid Build Coastguard Worker 
1409*7304104dSAndroid Build Coastguard Worker   fputc_unlocked ('\n', stdout);
1410*7304104dSAndroid Build Coastguard Worker }
1411*7304104dSAndroid Build Coastguard Worker 
1412*7304104dSAndroid Build Coastguard Worker 
1413*7304104dSAndroid Build Coastguard Worker /* Print the program header.  */
1414*7304104dSAndroid Build Coastguard Worker static void
print_phdr(Ebl * ebl,GElf_Ehdr * ehdr)1415*7304104dSAndroid Build Coastguard Worker print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
1416*7304104dSAndroid Build Coastguard Worker {
1417*7304104dSAndroid Build Coastguard Worker   if (phnum == 0)
1418*7304104dSAndroid Build Coastguard Worker     /* No program header, this is OK in relocatable objects.  */
1419*7304104dSAndroid Build Coastguard Worker     return;
1420*7304104dSAndroid Build Coastguard Worker 
1421*7304104dSAndroid Build Coastguard Worker   puts (_("Program Headers:"));
1422*7304104dSAndroid Build Coastguard Worker   if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
1423*7304104dSAndroid Build Coastguard Worker     puts (_("\
1424*7304104dSAndroid Build Coastguard Worker   Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
1425*7304104dSAndroid Build Coastguard Worker   else
1426*7304104dSAndroid Build Coastguard Worker     puts (_("\
1427*7304104dSAndroid Build Coastguard Worker   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
1428*7304104dSAndroid Build Coastguard Worker 
1429*7304104dSAndroid Build Coastguard Worker   /* Process all program headers.  */
1430*7304104dSAndroid Build Coastguard Worker   bool has_relro = false;
1431*7304104dSAndroid Build Coastguard Worker   GElf_Addr relro_from = 0;
1432*7304104dSAndroid Build Coastguard Worker   GElf_Addr relro_to = 0;
1433*7304104dSAndroid Build Coastguard Worker   for (size_t cnt = 0; cnt < phnum; ++cnt)
1434*7304104dSAndroid Build Coastguard Worker     {
1435*7304104dSAndroid Build Coastguard Worker       char buf[128];
1436*7304104dSAndroid Build Coastguard Worker       GElf_Phdr mem;
1437*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
1438*7304104dSAndroid Build Coastguard Worker 
1439*7304104dSAndroid Build Coastguard Worker       /* If for some reason the header cannot be returned show this.  */
1440*7304104dSAndroid Build Coastguard Worker       if (unlikely (phdr == NULL))
1441*7304104dSAndroid Build Coastguard Worker 	{
1442*7304104dSAndroid Build Coastguard Worker 	  puts ("  ???");
1443*7304104dSAndroid Build Coastguard Worker 	  continue;
1444*7304104dSAndroid Build Coastguard Worker 	}
1445*7304104dSAndroid Build Coastguard Worker 
1446*7304104dSAndroid Build Coastguard Worker       printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
1447*7304104dSAndroid Build Coastguard Worker 	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
1448*7304104dSAndroid Build Coastguard Worker 	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
1449*7304104dSAndroid Build Coastguard Worker 	      phdr->p_offset,
1450*7304104dSAndroid Build Coastguard Worker 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
1451*7304104dSAndroid Build Coastguard Worker 	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
1452*7304104dSAndroid Build Coastguard Worker 	      phdr->p_filesz,
1453*7304104dSAndroid Build Coastguard Worker 	      phdr->p_memsz,
1454*7304104dSAndroid Build Coastguard Worker 	      phdr->p_flags & PF_R ? 'R' : ' ',
1455*7304104dSAndroid Build Coastguard Worker 	      phdr->p_flags & PF_W ? 'W' : ' ',
1456*7304104dSAndroid Build Coastguard Worker 	      phdr->p_flags & PF_X ? 'E' : ' ',
1457*7304104dSAndroid Build Coastguard Worker 	      phdr->p_align);
1458*7304104dSAndroid Build Coastguard Worker 
1459*7304104dSAndroid Build Coastguard Worker       if (phdr->p_type == PT_INTERP)
1460*7304104dSAndroid Build Coastguard Worker 	{
1461*7304104dSAndroid Build Coastguard Worker 	  /* If we are sure the file offset is valid then we can show
1462*7304104dSAndroid Build Coastguard Worker 	     the user the name of the interpreter.  We check whether
1463*7304104dSAndroid Build Coastguard Worker 	     there is a section at the file offset.  Normally there
1464*7304104dSAndroid Build Coastguard Worker 	     would be a section called ".interp".  But in separate
1465*7304104dSAndroid Build Coastguard Worker 	     .debug files it is a NOBITS section (and so doesn't match
1466*7304104dSAndroid Build Coastguard Worker 	     with gelf_offscn).  Which probably means the offset is
1467*7304104dSAndroid Build Coastguard Worker 	     not valid another reason could be because the ELF file
1468*7304104dSAndroid Build Coastguard Worker 	     just doesn't contain any section headers, in that case
1469*7304104dSAndroid Build Coastguard Worker 	     just play it safe and don't display anything.  */
1470*7304104dSAndroid Build Coastguard Worker 
1471*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
1472*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr shdr_mem;
1473*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1474*7304104dSAndroid Build Coastguard Worker 
1475*7304104dSAndroid Build Coastguard Worker 	  size_t maxsize;
1476*7304104dSAndroid Build Coastguard Worker 	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
1477*7304104dSAndroid Build Coastguard Worker 
1478*7304104dSAndroid Build Coastguard Worker 	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
1479*7304104dSAndroid Build Coastguard Worker 	      && filedata != NULL && phdr->p_offset < maxsize
1480*7304104dSAndroid Build Coastguard Worker 	      && phdr->p_filesz <= maxsize - phdr->p_offset
1481*7304104dSAndroid Build Coastguard Worker 	      && memchr (filedata + phdr->p_offset, '\0',
1482*7304104dSAndroid Build Coastguard Worker 			 phdr->p_filesz) != NULL)
1483*7304104dSAndroid Build Coastguard Worker 	    printf (_("\t[Requesting program interpreter: %s]\n"),
1484*7304104dSAndroid Build Coastguard Worker 		    filedata + phdr->p_offset);
1485*7304104dSAndroid Build Coastguard Worker 	}
1486*7304104dSAndroid Build Coastguard Worker       else if (phdr->p_type == PT_GNU_RELRO)
1487*7304104dSAndroid Build Coastguard Worker 	{
1488*7304104dSAndroid Build Coastguard Worker 	  has_relro = true;
1489*7304104dSAndroid Build Coastguard Worker 	  relro_from = phdr->p_vaddr;
1490*7304104dSAndroid Build Coastguard Worker 	  relro_to = relro_from + phdr->p_memsz;
1491*7304104dSAndroid Build Coastguard Worker 	}
1492*7304104dSAndroid Build Coastguard Worker     }
1493*7304104dSAndroid Build Coastguard Worker 
1494*7304104dSAndroid Build Coastguard Worker   size_t sections;
1495*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
1496*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get number of sections: %s"),
1497*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
1498*7304104dSAndroid Build Coastguard Worker 
1499*7304104dSAndroid Build Coastguard Worker   if (sections == 0)
1500*7304104dSAndroid Build Coastguard Worker     /* No sections in the file.  Punt.  */
1501*7304104dSAndroid Build Coastguard Worker     return;
1502*7304104dSAndroid Build Coastguard Worker 
1503*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
1504*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
1505*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1506*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
1507*7304104dSAndroid Build Coastguard Worker 
1508*7304104dSAndroid Build Coastguard Worker   puts (_("\n Section to Segment mapping:\n  Segment Sections..."));
1509*7304104dSAndroid Build Coastguard Worker 
1510*7304104dSAndroid Build Coastguard Worker   for (size_t cnt = 0; cnt < phnum; ++cnt)
1511*7304104dSAndroid Build Coastguard Worker     {
1512*7304104dSAndroid Build Coastguard Worker       /* Print the segment number.  */
1513*7304104dSAndroid Build Coastguard Worker       printf ("   %2.2zu     ", cnt);
1514*7304104dSAndroid Build Coastguard Worker 
1515*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
1516*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
1517*7304104dSAndroid Build Coastguard Worker       /* This must not happen.  */
1518*7304104dSAndroid Build Coastguard Worker       if (unlikely (phdr == NULL))
1519*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get program header: %s"),
1520*7304104dSAndroid Build Coastguard Worker 		    elf_errmsg (-1));
1521*7304104dSAndroid Build Coastguard Worker 
1522*7304104dSAndroid Build Coastguard Worker       /* Iterate over the sections.  */
1523*7304104dSAndroid Build Coastguard Worker       bool in_relro = false;
1524*7304104dSAndroid Build Coastguard Worker       bool in_ro = false;
1525*7304104dSAndroid Build Coastguard Worker       for (size_t inner = 1; inner < shnum; ++inner)
1526*7304104dSAndroid Build Coastguard Worker 	{
1527*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
1528*7304104dSAndroid Build Coastguard Worker 	  /* This should not happen.  */
1529*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (scn == NULL))
1530*7304104dSAndroid Build Coastguard Worker 	    error_exit (0, _("cannot get section: %s"),
1531*7304104dSAndroid Build Coastguard Worker 			elf_errmsg (-1));
1532*7304104dSAndroid Build Coastguard Worker 
1533*7304104dSAndroid Build Coastguard Worker 	  /* Get the section header.  */
1534*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr shdr_mem;
1535*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1536*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (shdr == NULL))
1537*7304104dSAndroid Build Coastguard Worker 	    error_exit (0, _("cannot get section header: %s"),
1538*7304104dSAndroid Build Coastguard Worker 			elf_errmsg (-1));
1539*7304104dSAndroid Build Coastguard Worker 
1540*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_size > 0
1541*7304104dSAndroid Build Coastguard Worker 	      /* Compare allocated sections by VMA, unallocated
1542*7304104dSAndroid Build Coastguard Worker 		 sections by file offset.  */
1543*7304104dSAndroid Build Coastguard Worker 	      && (shdr->sh_flags & SHF_ALLOC
1544*7304104dSAndroid Build Coastguard Worker 		  ? (shdr->sh_addr >= phdr->p_vaddr
1545*7304104dSAndroid Build Coastguard Worker 		     && (shdr->sh_addr + shdr->sh_size
1546*7304104dSAndroid Build Coastguard Worker 			 <= phdr->p_vaddr + phdr->p_memsz))
1547*7304104dSAndroid Build Coastguard Worker 		  : (shdr->sh_offset >= phdr->p_offset
1548*7304104dSAndroid Build Coastguard Worker 		     && (shdr->sh_offset + shdr->sh_size
1549*7304104dSAndroid Build Coastguard Worker 			 <= phdr->p_offset + phdr->p_filesz))))
1550*7304104dSAndroid Build Coastguard Worker 	    {
1551*7304104dSAndroid Build Coastguard Worker 	      if (has_relro && !in_relro
1552*7304104dSAndroid Build Coastguard Worker 		  && shdr->sh_addr >= relro_from
1553*7304104dSAndroid Build Coastguard Worker 		  && shdr->sh_addr + shdr->sh_size <= relro_to)
1554*7304104dSAndroid Build Coastguard Worker 		{
1555*7304104dSAndroid Build Coastguard Worker 		  fputs_unlocked (" [RELRO:", stdout);
1556*7304104dSAndroid Build Coastguard Worker 		  in_relro = true;
1557*7304104dSAndroid Build Coastguard Worker 		}
1558*7304104dSAndroid Build Coastguard Worker 	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
1559*7304104dSAndroid Build Coastguard Worker 		{
1560*7304104dSAndroid Build Coastguard Worker 		  fputs_unlocked ("]", stdout);
1561*7304104dSAndroid Build Coastguard Worker 		  in_relro =  false;
1562*7304104dSAndroid Build Coastguard Worker 		}
1563*7304104dSAndroid Build Coastguard Worker 	      else if (has_relro && in_relro
1564*7304104dSAndroid Build Coastguard Worker 		       && shdr->sh_addr + shdr->sh_size > relro_to)
1565*7304104dSAndroid Build Coastguard Worker 		fputs_unlocked ("] <RELRO:", stdout);
1566*7304104dSAndroid Build Coastguard Worker 	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
1567*7304104dSAndroid Build Coastguard Worker 		{
1568*7304104dSAndroid Build Coastguard Worker 		  if (!in_ro)
1569*7304104dSAndroid Build Coastguard Worker 		    {
1570*7304104dSAndroid Build Coastguard Worker 		      fputs_unlocked (" [RO:", stdout);
1571*7304104dSAndroid Build Coastguard Worker 		      in_ro = true;
1572*7304104dSAndroid Build Coastguard Worker 		    }
1573*7304104dSAndroid Build Coastguard Worker 		}
1574*7304104dSAndroid Build Coastguard Worker 	      else
1575*7304104dSAndroid Build Coastguard Worker 		{
1576*7304104dSAndroid Build Coastguard Worker 		  /* Determine the segment this section is part of.  */
1577*7304104dSAndroid Build Coastguard Worker 		  size_t cnt2;
1578*7304104dSAndroid Build Coastguard Worker 		  GElf_Phdr phdr2_mem;
1579*7304104dSAndroid Build Coastguard Worker 		  GElf_Phdr *phdr2 = NULL;
1580*7304104dSAndroid Build Coastguard Worker 		  for (cnt2 = 0; cnt2 < phnum; ++cnt2)
1581*7304104dSAndroid Build Coastguard Worker 		    {
1582*7304104dSAndroid Build Coastguard Worker 		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
1583*7304104dSAndroid Build Coastguard Worker 
1584*7304104dSAndroid Build Coastguard Worker 		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
1585*7304104dSAndroid Build Coastguard Worker 			  && shdr->sh_addr >= phdr2->p_vaddr
1586*7304104dSAndroid Build Coastguard Worker 			  && (shdr->sh_addr + shdr->sh_size
1587*7304104dSAndroid Build Coastguard Worker 			      <= phdr2->p_vaddr + phdr2->p_memsz))
1588*7304104dSAndroid Build Coastguard Worker 			break;
1589*7304104dSAndroid Build Coastguard Worker 		    }
1590*7304104dSAndroid Build Coastguard Worker 
1591*7304104dSAndroid Build Coastguard Worker 		  if (cnt2 < phnum)
1592*7304104dSAndroid Build Coastguard Worker 		    {
1593*7304104dSAndroid Build Coastguard Worker 		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
1594*7304104dSAndroid Build Coastguard Worker 			{
1595*7304104dSAndroid Build Coastguard Worker 			  fputs_unlocked (" [RO:", stdout);
1596*7304104dSAndroid Build Coastguard Worker 			  in_ro = true;
1597*7304104dSAndroid Build Coastguard Worker 			}
1598*7304104dSAndroid Build Coastguard Worker 		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
1599*7304104dSAndroid Build Coastguard Worker 			{
1600*7304104dSAndroid Build Coastguard Worker 			  fputs_unlocked ("]", stdout);
1601*7304104dSAndroid Build Coastguard Worker 			  in_ro = false;
1602*7304104dSAndroid Build Coastguard Worker 			}
1603*7304104dSAndroid Build Coastguard Worker 		    }
1604*7304104dSAndroid Build Coastguard Worker 		}
1605*7304104dSAndroid Build Coastguard Worker 
1606*7304104dSAndroid Build Coastguard Worker 	      printf (" %s",
1607*7304104dSAndroid Build Coastguard Worker 		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1608*7304104dSAndroid Build Coastguard Worker 
1609*7304104dSAndroid Build Coastguard Worker 	      /* Signal that this section is only partially covered.  */
1610*7304104dSAndroid Build Coastguard Worker 	      if (has_relro && in_relro
1611*7304104dSAndroid Build Coastguard Worker 		       && shdr->sh_addr + shdr->sh_size > relro_to)
1612*7304104dSAndroid Build Coastguard Worker 		{
1613*7304104dSAndroid Build Coastguard Worker 		  fputs_unlocked (">", stdout);
1614*7304104dSAndroid Build Coastguard Worker 		  in_relro =  false;
1615*7304104dSAndroid Build Coastguard Worker 		}
1616*7304104dSAndroid Build Coastguard Worker 	    }
1617*7304104dSAndroid Build Coastguard Worker 	}
1618*7304104dSAndroid Build Coastguard Worker       if (in_relro || in_ro)
1619*7304104dSAndroid Build Coastguard Worker 	fputs_unlocked ("]", stdout);
1620*7304104dSAndroid Build Coastguard Worker 
1621*7304104dSAndroid Build Coastguard Worker       /* Finish the line.  */
1622*7304104dSAndroid Build Coastguard Worker       fputc_unlocked ('\n', stdout);
1623*7304104dSAndroid Build Coastguard Worker     }
1624*7304104dSAndroid Build Coastguard Worker }
1625*7304104dSAndroid Build Coastguard Worker 
1626*7304104dSAndroid Build Coastguard Worker 
1627*7304104dSAndroid Build Coastguard Worker static const char *
section_name(Ebl * ebl,GElf_Shdr * shdr)1628*7304104dSAndroid Build Coastguard Worker section_name (Ebl *ebl, GElf_Shdr *shdr)
1629*7304104dSAndroid Build Coastguard Worker {
1630*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
1631*7304104dSAndroid Build Coastguard Worker   if (shdr == NULL || elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
1632*7304104dSAndroid Build Coastguard Worker     return "???";
1633*7304104dSAndroid Build Coastguard Worker   return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
1634*7304104dSAndroid Build Coastguard Worker }
1635*7304104dSAndroid Build Coastguard Worker 
1636*7304104dSAndroid Build Coastguard Worker 
1637*7304104dSAndroid Build Coastguard Worker static void
handle_scngrp(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr)1638*7304104dSAndroid Build Coastguard Worker handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
1639*7304104dSAndroid Build Coastguard Worker {
1640*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
1641*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
1642*7304104dSAndroid Build Coastguard Worker 
1643*7304104dSAndroid Build Coastguard Worker   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
1644*7304104dSAndroid Build Coastguard Worker   GElf_Shdr symshdr_mem;
1645*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1646*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = elf_getdata (symscn, NULL);
1647*7304104dSAndroid Build Coastguard Worker 
1648*7304104dSAndroid Build Coastguard Worker   if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
1649*7304104dSAndroid Build Coastguard Worker       || symdata == NULL)
1650*7304104dSAndroid Build Coastguard Worker     return;
1651*7304104dSAndroid Build Coastguard Worker 
1652*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
1653*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
1654*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1655*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
1656*7304104dSAndroid Build Coastguard Worker 
1657*7304104dSAndroid Build Coastguard Worker   Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
1658*7304104dSAndroid Build Coastguard Worker 
1659*7304104dSAndroid Build Coastguard Worker   GElf_Sym sym_mem;
1660*7304104dSAndroid Build Coastguard Worker   GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
1661*7304104dSAndroid Build Coastguard Worker 
1662*7304104dSAndroid Build Coastguard Worker   printf ((grpref[0] & GRP_COMDAT)
1663*7304104dSAndroid Build Coastguard Worker 	  ? ngettext ("\
1664*7304104dSAndroid Build Coastguard Worker \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
1665*7304104dSAndroid Build Coastguard Worker 		      "\
1666*7304104dSAndroid Build Coastguard Worker \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1667*7304104dSAndroid Build Coastguard Worker 		      data->d_size / sizeof (Elf32_Word) - 1)
1668*7304104dSAndroid Build Coastguard Worker 	  : ngettext ("\
1669*7304104dSAndroid Build Coastguard Worker \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
1670*7304104dSAndroid Build Coastguard Worker \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
1671*7304104dSAndroid Build Coastguard Worker 		      data->d_size / sizeof (Elf32_Word) - 1),
1672*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn),
1673*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
1674*7304104dSAndroid Build Coastguard Worker 	  (sym == NULL ? NULL
1675*7304104dSAndroid Build Coastguard Worker 	   : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
1676*7304104dSAndroid Build Coastguard Worker 	  ?: _("<INVALID SYMBOL>"),
1677*7304104dSAndroid Build Coastguard Worker 	  data->d_size / sizeof (Elf32_Word) - 1);
1678*7304104dSAndroid Build Coastguard Worker 
1679*7304104dSAndroid Build Coastguard Worker   for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
1680*7304104dSAndroid Build Coastguard Worker     {
1681*7304104dSAndroid Build Coastguard Worker       GElf_Shdr grpshdr_mem;
1682*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
1683*7304104dSAndroid Build Coastguard Worker 					 &grpshdr_mem);
1684*7304104dSAndroid Build Coastguard Worker 
1685*7304104dSAndroid Build Coastguard Worker       const char *str;
1686*7304104dSAndroid Build Coastguard Worker       printf ("  [%2u] %s\n",
1687*7304104dSAndroid Build Coastguard Worker 	      grpref[cnt],
1688*7304104dSAndroid Build Coastguard Worker 	      grpshdr != NULL
1689*7304104dSAndroid Build Coastguard Worker 	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
1690*7304104dSAndroid Build Coastguard Worker 	      ? str : _("<INVALID SECTION>"));
1691*7304104dSAndroid Build Coastguard Worker     }
1692*7304104dSAndroid Build Coastguard Worker }
1693*7304104dSAndroid Build Coastguard Worker 
1694*7304104dSAndroid Build Coastguard Worker 
1695*7304104dSAndroid Build Coastguard Worker static void
print_scngrp(Ebl * ebl)1696*7304104dSAndroid Build Coastguard Worker print_scngrp (Ebl *ebl)
1697*7304104dSAndroid Build Coastguard Worker {
1698*7304104dSAndroid Build Coastguard Worker   /* Find all relocation sections and handle them.  */
1699*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
1700*7304104dSAndroid Build Coastguard Worker 
1701*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
1702*7304104dSAndroid Build Coastguard Worker     {
1703*7304104dSAndroid Build Coastguard Worker        /* Handle the section if it is a symbol table.  */
1704*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
1705*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1706*7304104dSAndroid Build Coastguard Worker 
1707*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL && shdr->sh_type == SHT_GROUP)
1708*7304104dSAndroid Build Coastguard Worker 	{
1709*7304104dSAndroid Build Coastguard Worker 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1710*7304104dSAndroid Build Coastguard Worker 	    {
1711*7304104dSAndroid Build Coastguard Worker 	      if (elf_compress (scn, 0, 0) < 0)
1712*7304104dSAndroid Build Coastguard Worker 		printf ("WARNING: %s [%zd]\n",
1713*7304104dSAndroid Build Coastguard Worker 			_("Couldn't uncompress section"),
1714*7304104dSAndroid Build Coastguard Worker 			elf_ndxscn (scn));
1715*7304104dSAndroid Build Coastguard Worker 	      shdr = gelf_getshdr (scn, &shdr_mem);
1716*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (shdr == NULL))
1717*7304104dSAndroid Build Coastguard Worker 		error_exit (0, _("cannot get section [%zd] header: %s"),
1718*7304104dSAndroid Build Coastguard Worker 			    elf_ndxscn (scn),
1719*7304104dSAndroid Build Coastguard Worker 			    elf_errmsg (-1));
1720*7304104dSAndroid Build Coastguard Worker 	    }
1721*7304104dSAndroid Build Coastguard Worker 	  handle_scngrp (ebl, scn, shdr);
1722*7304104dSAndroid Build Coastguard Worker 	}
1723*7304104dSAndroid Build Coastguard Worker     }
1724*7304104dSAndroid Build Coastguard Worker }
1725*7304104dSAndroid Build Coastguard Worker 
1726*7304104dSAndroid Build Coastguard Worker 
1727*7304104dSAndroid Build Coastguard Worker static const struct flags
1728*7304104dSAndroid Build Coastguard Worker {
1729*7304104dSAndroid Build Coastguard Worker   int mask;
1730*7304104dSAndroid Build Coastguard Worker   const char *str;
1731*7304104dSAndroid Build Coastguard Worker } dt_flags[] =
1732*7304104dSAndroid Build Coastguard Worker   {
1733*7304104dSAndroid Build Coastguard Worker     { DF_ORIGIN, "ORIGIN" },
1734*7304104dSAndroid Build Coastguard Worker     { DF_SYMBOLIC, "SYMBOLIC" },
1735*7304104dSAndroid Build Coastguard Worker     { DF_TEXTREL, "TEXTREL" },
1736*7304104dSAndroid Build Coastguard Worker     { DF_BIND_NOW, "BIND_NOW" },
1737*7304104dSAndroid Build Coastguard Worker     { DF_STATIC_TLS, "STATIC_TLS" }
1738*7304104dSAndroid Build Coastguard Worker   };
1739*7304104dSAndroid Build Coastguard Worker static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
1740*7304104dSAndroid Build Coastguard Worker 
1741*7304104dSAndroid Build Coastguard Worker static const struct flags dt_flags_1[] =
1742*7304104dSAndroid Build Coastguard Worker   {
1743*7304104dSAndroid Build Coastguard Worker     { DF_1_NOW, "NOW" },
1744*7304104dSAndroid Build Coastguard Worker     { DF_1_GLOBAL, "GLOBAL" },
1745*7304104dSAndroid Build Coastguard Worker     { DF_1_GROUP, "GROUP" },
1746*7304104dSAndroid Build Coastguard Worker     { DF_1_NODELETE, "NODELETE" },
1747*7304104dSAndroid Build Coastguard Worker     { DF_1_LOADFLTR, "LOADFLTR" },
1748*7304104dSAndroid Build Coastguard Worker     { DF_1_INITFIRST, "INITFIRST" },
1749*7304104dSAndroid Build Coastguard Worker     { DF_1_NOOPEN, "NOOPEN" },
1750*7304104dSAndroid Build Coastguard Worker     { DF_1_ORIGIN, "ORIGIN" },
1751*7304104dSAndroid Build Coastguard Worker     { DF_1_DIRECT, "DIRECT" },
1752*7304104dSAndroid Build Coastguard Worker     { DF_1_TRANS, "TRANS" },
1753*7304104dSAndroid Build Coastguard Worker     { DF_1_INTERPOSE, "INTERPOSE" },
1754*7304104dSAndroid Build Coastguard Worker     { DF_1_NODEFLIB, "NODEFLIB" },
1755*7304104dSAndroid Build Coastguard Worker     { DF_1_NODUMP, "NODUMP" },
1756*7304104dSAndroid Build Coastguard Worker     { DF_1_CONFALT, "CONFALT" },
1757*7304104dSAndroid Build Coastguard Worker     { DF_1_ENDFILTEE, "ENDFILTEE" },
1758*7304104dSAndroid Build Coastguard Worker     { DF_1_DISPRELDNE, "DISPRELDNE" },
1759*7304104dSAndroid Build Coastguard Worker     { DF_1_DISPRELPND, "DISPRELPND" },
1760*7304104dSAndroid Build Coastguard Worker   };
1761*7304104dSAndroid Build Coastguard Worker static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
1762*7304104dSAndroid Build Coastguard Worker 
1763*7304104dSAndroid Build Coastguard Worker static const struct flags dt_feature_1[] =
1764*7304104dSAndroid Build Coastguard Worker   {
1765*7304104dSAndroid Build Coastguard Worker     { DTF_1_PARINIT, "PARINIT" },
1766*7304104dSAndroid Build Coastguard Worker     { DTF_1_CONFEXP, "CONFEXP" }
1767*7304104dSAndroid Build Coastguard Worker   };
1768*7304104dSAndroid Build Coastguard Worker static const int ndt_feature_1 = (sizeof (dt_feature_1)
1769*7304104dSAndroid Build Coastguard Worker 				  / sizeof (dt_feature_1[0]));
1770*7304104dSAndroid Build Coastguard Worker 
1771*7304104dSAndroid Build Coastguard Worker static const struct flags dt_posflag_1[] =
1772*7304104dSAndroid Build Coastguard Worker   {
1773*7304104dSAndroid Build Coastguard Worker     { DF_P1_LAZYLOAD, "LAZYLOAD" },
1774*7304104dSAndroid Build Coastguard Worker     { DF_P1_GROUPPERM, "GROUPPERM" }
1775*7304104dSAndroid Build Coastguard Worker   };
1776*7304104dSAndroid Build Coastguard Worker static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
1777*7304104dSAndroid Build Coastguard Worker 				  / sizeof (dt_posflag_1[0]));
1778*7304104dSAndroid Build Coastguard Worker 
1779*7304104dSAndroid Build Coastguard Worker 
1780*7304104dSAndroid Build Coastguard Worker static void
print_flags(int class,GElf_Xword d_val,const struct flags * flags,int nflags)1781*7304104dSAndroid Build Coastguard Worker print_flags (int class, GElf_Xword d_val, const struct flags *flags,
1782*7304104dSAndroid Build Coastguard Worker 		int nflags)
1783*7304104dSAndroid Build Coastguard Worker {
1784*7304104dSAndroid Build Coastguard Worker   bool first = true;
1785*7304104dSAndroid Build Coastguard Worker   int cnt;
1786*7304104dSAndroid Build Coastguard Worker 
1787*7304104dSAndroid Build Coastguard Worker   for (cnt = 0; cnt < nflags; ++cnt)
1788*7304104dSAndroid Build Coastguard Worker     if (d_val & flags[cnt].mask)
1789*7304104dSAndroid Build Coastguard Worker       {
1790*7304104dSAndroid Build Coastguard Worker 	if (!first)
1791*7304104dSAndroid Build Coastguard Worker 	  putchar_unlocked (' ');
1792*7304104dSAndroid Build Coastguard Worker 	fputs_unlocked (flags[cnt].str, stdout);
1793*7304104dSAndroid Build Coastguard Worker 	d_val &= ~flags[cnt].mask;
1794*7304104dSAndroid Build Coastguard Worker 	first = false;
1795*7304104dSAndroid Build Coastguard Worker       }
1796*7304104dSAndroid Build Coastguard Worker 
1797*7304104dSAndroid Build Coastguard Worker   if (d_val != 0)
1798*7304104dSAndroid Build Coastguard Worker     {
1799*7304104dSAndroid Build Coastguard Worker       if (!first)
1800*7304104dSAndroid Build Coastguard Worker 	putchar_unlocked (' ');
1801*7304104dSAndroid Build Coastguard Worker       printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
1802*7304104dSAndroid Build Coastguard Worker     }
1803*7304104dSAndroid Build Coastguard Worker 
1804*7304104dSAndroid Build Coastguard Worker   putchar_unlocked ('\n');
1805*7304104dSAndroid Build Coastguard Worker }
1806*7304104dSAndroid Build Coastguard Worker 
1807*7304104dSAndroid Build Coastguard Worker 
1808*7304104dSAndroid Build Coastguard Worker static void
print_dt_flags(int class,GElf_Xword d_val)1809*7304104dSAndroid Build Coastguard Worker print_dt_flags (int class, GElf_Xword d_val)
1810*7304104dSAndroid Build Coastguard Worker {
1811*7304104dSAndroid Build Coastguard Worker   print_flags (class, d_val, dt_flags, ndt_flags);
1812*7304104dSAndroid Build Coastguard Worker }
1813*7304104dSAndroid Build Coastguard Worker 
1814*7304104dSAndroid Build Coastguard Worker 
1815*7304104dSAndroid Build Coastguard Worker static void
print_dt_flags_1(int class,GElf_Xword d_val)1816*7304104dSAndroid Build Coastguard Worker print_dt_flags_1 (int class, GElf_Xword d_val)
1817*7304104dSAndroid Build Coastguard Worker {
1818*7304104dSAndroid Build Coastguard Worker   print_flags (class, d_val, dt_flags_1, ndt_flags_1);
1819*7304104dSAndroid Build Coastguard Worker }
1820*7304104dSAndroid Build Coastguard Worker 
1821*7304104dSAndroid Build Coastguard Worker 
1822*7304104dSAndroid Build Coastguard Worker static void
print_dt_feature_1(int class,GElf_Xword d_val)1823*7304104dSAndroid Build Coastguard Worker print_dt_feature_1 (int class, GElf_Xword d_val)
1824*7304104dSAndroid Build Coastguard Worker {
1825*7304104dSAndroid Build Coastguard Worker   print_flags (class, d_val, dt_feature_1, ndt_feature_1);
1826*7304104dSAndroid Build Coastguard Worker }
1827*7304104dSAndroid Build Coastguard Worker 
1828*7304104dSAndroid Build Coastguard Worker 
1829*7304104dSAndroid Build Coastguard Worker static void
print_dt_posflag_1(int class,GElf_Xword d_val)1830*7304104dSAndroid Build Coastguard Worker print_dt_posflag_1 (int class, GElf_Xword d_val)
1831*7304104dSAndroid Build Coastguard Worker {
1832*7304104dSAndroid Build Coastguard Worker   print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
1833*7304104dSAndroid Build Coastguard Worker }
1834*7304104dSAndroid Build Coastguard Worker 
1835*7304104dSAndroid Build Coastguard Worker 
1836*7304104dSAndroid Build Coastguard Worker static size_t
get_dyn_ents(Elf_Data * dyn_data)1837*7304104dSAndroid Build Coastguard Worker get_dyn_ents (Elf_Data * dyn_data)
1838*7304104dSAndroid Build Coastguard Worker {
1839*7304104dSAndroid Build Coastguard Worker   GElf_Dyn *dyn;
1840*7304104dSAndroid Build Coastguard Worker   GElf_Dyn dyn_mem;
1841*7304104dSAndroid Build Coastguard Worker   size_t dyn_idx = 0;
1842*7304104dSAndroid Build Coastguard Worker   do
1843*7304104dSAndroid Build Coastguard Worker     {
1844*7304104dSAndroid Build Coastguard Worker       dyn = gelf_getdyn(dyn_data, dyn_idx, &dyn_mem);
1845*7304104dSAndroid Build Coastguard Worker       if (dyn != NULL)
1846*7304104dSAndroid Build Coastguard Worker 	++dyn_idx;
1847*7304104dSAndroid Build Coastguard Worker     }
1848*7304104dSAndroid Build Coastguard Worker   while (dyn != NULL && dyn->d_tag != DT_NULL);
1849*7304104dSAndroid Build Coastguard Worker 
1850*7304104dSAndroid Build Coastguard Worker   return dyn_idx;
1851*7304104dSAndroid Build Coastguard Worker }
1852*7304104dSAndroid Build Coastguard Worker 
1853*7304104dSAndroid Build Coastguard Worker 
1854*7304104dSAndroid Build Coastguard Worker static void
handle_dynamic(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr,GElf_Phdr * phdr)1855*7304104dSAndroid Build Coastguard Worker handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, GElf_Phdr *phdr)
1856*7304104dSAndroid Build Coastguard Worker {
1857*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
1858*7304104dSAndroid Build Coastguard Worker   GElf_Shdr glink_mem;
1859*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *glink;
1860*7304104dSAndroid Build Coastguard Worker   Elf_Data *data;
1861*7304104dSAndroid Build Coastguard Worker   size_t cnt;
1862*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
1863*7304104dSAndroid Build Coastguard Worker   size_t dyn_ents;
1864*7304104dSAndroid Build Coastguard Worker 
1865*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
1866*7304104dSAndroid Build Coastguard Worker   if (use_dynamic_segment && phdr != NULL)
1867*7304104dSAndroid Build Coastguard Worker     data = elf_getdata_rawchunk(ebl->elf, phdr->p_offset,
1868*7304104dSAndroid Build Coastguard Worker 				phdr->p_filesz, ELF_T_DYN);
1869*7304104dSAndroid Build Coastguard Worker   else
1870*7304104dSAndroid Build Coastguard Worker     data = elf_getdata (scn, NULL);
1871*7304104dSAndroid Build Coastguard Worker 
1872*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
1873*7304104dSAndroid Build Coastguard Worker     return;
1874*7304104dSAndroid Build Coastguard Worker 
1875*7304104dSAndroid Build Coastguard Worker   /* Get the dynamic section entry number */
1876*7304104dSAndroid Build Coastguard Worker   dyn_ents = get_dyn_ents (data);
1877*7304104dSAndroid Build Coastguard Worker 
1878*7304104dSAndroid Build Coastguard Worker   if (!use_dynamic_segment && shdr != NULL)
1879*7304104dSAndroid Build Coastguard Worker     {
1880*7304104dSAndroid Build Coastguard Worker       /* Get the section header string table index.  */
1881*7304104dSAndroid Build Coastguard Worker       if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
1882*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get section header string table index"));
1883*7304104dSAndroid Build Coastguard Worker 
1884*7304104dSAndroid Build Coastguard Worker       glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
1885*7304104dSAndroid Build Coastguard Worker       if (glink == NULL)
1886*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("invalid sh_link value in section %zu"),
1887*7304104dSAndroid Build Coastguard Worker 		    elf_ndxscn (scn));
1888*7304104dSAndroid Build Coastguard Worker 
1889*7304104dSAndroid Build Coastguard Worker       printf (ngettext ("\
1890*7304104dSAndroid Build Coastguard Worker \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1891*7304104dSAndroid Build Coastguard Worker 		    "\
1892*7304104dSAndroid Build Coastguard Worker \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
1893*7304104dSAndroid Build Coastguard Worker 			dyn_ents),
1894*7304104dSAndroid Build Coastguard Worker 	      (unsigned long int) dyn_ents,
1895*7304104dSAndroid Build Coastguard Worker 	      class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
1896*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_offset,
1897*7304104dSAndroid Build Coastguard Worker 	      (int) shdr->sh_link,
1898*7304104dSAndroid Build Coastguard Worker 	      elf_strptr (ebl->elf, shstrndx, glink->sh_name));
1899*7304104dSAndroid Build Coastguard Worker     }
1900*7304104dSAndroid Build Coastguard Worker   else if (phdr != NULL)
1901*7304104dSAndroid Build Coastguard Worker     {
1902*7304104dSAndroid Build Coastguard Worker       printf (ngettext ("\
1903*7304104dSAndroid Build Coastguard Worker \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "\n",
1904*7304104dSAndroid Build Coastguard Worker 		    "\
1905*7304104dSAndroid Build Coastguard Worker \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "\n",
1906*7304104dSAndroid Build Coastguard Worker 			dyn_ents),
1907*7304104dSAndroid Build Coastguard Worker 	      (unsigned long int) dyn_ents,
1908*7304104dSAndroid Build Coastguard Worker 	      class == ELFCLASS32 ? 10 : 18, phdr->p_paddr,
1909*7304104dSAndroid Build Coastguard Worker 	      phdr->p_offset);
1910*7304104dSAndroid Build Coastguard Worker     }
1911*7304104dSAndroid Build Coastguard Worker 
1912*7304104dSAndroid Build Coastguard Worker   fputs_unlocked (_("  Type              Value\n"), stdout);
1913*7304104dSAndroid Build Coastguard Worker 
1914*7304104dSAndroid Build Coastguard Worker   /* if --use-dynamic option is enabled,
1915*7304104dSAndroid Build Coastguard Worker      use the string table to get the related library info.  */
1916*7304104dSAndroid Build Coastguard Worker   Elf_Data *strtab_data = NULL;
1917*7304104dSAndroid Build Coastguard Worker   if (use_dynamic_segment && phdr != NULL)
1918*7304104dSAndroid Build Coastguard Worker     {
1919*7304104dSAndroid Build Coastguard Worker       strtab_data = get_dynscn_strtab(ebl->elf, phdr);
1920*7304104dSAndroid Build Coastguard Worker       if (strtab_data == NULL)
1921*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get string table by using dynamic segment"));
1922*7304104dSAndroid Build Coastguard Worker     }
1923*7304104dSAndroid Build Coastguard Worker 
1924*7304104dSAndroid Build Coastguard Worker   for (cnt = 0; cnt < dyn_ents; ++cnt)
1925*7304104dSAndroid Build Coastguard Worker     {
1926*7304104dSAndroid Build Coastguard Worker       GElf_Dyn dynmem;
1927*7304104dSAndroid Build Coastguard Worker       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
1928*7304104dSAndroid Build Coastguard Worker       if (dyn == NULL)
1929*7304104dSAndroid Build Coastguard Worker 	break;
1930*7304104dSAndroid Build Coastguard Worker 
1931*7304104dSAndroid Build Coastguard Worker       char buf[64];
1932*7304104dSAndroid Build Coastguard Worker       printf ("  %-17s ",
1933*7304104dSAndroid Build Coastguard Worker 	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
1934*7304104dSAndroid Build Coastguard Worker 
1935*7304104dSAndroid Build Coastguard Worker       char *name = NULL;
1936*7304104dSAndroid Build Coastguard Worker       if (dyn->d_tag == DT_NEEDED
1937*7304104dSAndroid Build Coastguard Worker 	  || dyn->d_tag == DT_SONAME
1938*7304104dSAndroid Build Coastguard Worker 	  || dyn->d_tag == DT_RPATH
1939*7304104dSAndroid Build Coastguard Worker 	  || dyn->d_tag == DT_RUNPATH)
1940*7304104dSAndroid Build Coastguard Worker 	{
1941*7304104dSAndroid Build Coastguard Worker 	  if (! use_dynamic_segment && shdr != NULL)
1942*7304104dSAndroid Build Coastguard Worker 	    name = elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val);
1943*7304104dSAndroid Build Coastguard Worker 	  else if (dyn->d_un.d_val < strtab_data->d_size
1944*7304104dSAndroid Build Coastguard Worker 		   && memrchr (strtab_data->d_buf + dyn->d_un.d_val, '\0',
1945*7304104dSAndroid Build Coastguard Worker 			       strtab_data->d_size - 1 - dyn->d_un.d_val) != NULL)
1946*7304104dSAndroid Build Coastguard Worker 	    name = ((char *) strtab_data->d_buf) + dyn->d_un.d_val;
1947*7304104dSAndroid Build Coastguard Worker 	}
1948*7304104dSAndroid Build Coastguard Worker 
1949*7304104dSAndroid Build Coastguard Worker       switch (dyn->d_tag)
1950*7304104dSAndroid Build Coastguard Worker 	{
1951*7304104dSAndroid Build Coastguard Worker 	case DT_NULL:
1952*7304104dSAndroid Build Coastguard Worker 	case DT_DEBUG:
1953*7304104dSAndroid Build Coastguard Worker 	case DT_BIND_NOW:
1954*7304104dSAndroid Build Coastguard Worker 	case DT_TEXTREL:
1955*7304104dSAndroid Build Coastguard Worker 	  /* No further output.  */
1956*7304104dSAndroid Build Coastguard Worker 	  fputc_unlocked ('\n', stdout);
1957*7304104dSAndroid Build Coastguard Worker 	  break;
1958*7304104dSAndroid Build Coastguard Worker 
1959*7304104dSAndroid Build Coastguard Worker 	case DT_NEEDED:
1960*7304104dSAndroid Build Coastguard Worker 	  printf (_("Shared library: [%s]\n"), name);
1961*7304104dSAndroid Build Coastguard Worker 	  break;
1962*7304104dSAndroid Build Coastguard Worker 
1963*7304104dSAndroid Build Coastguard Worker 	case DT_SONAME:
1964*7304104dSAndroid Build Coastguard Worker 	  printf (_("Library soname: [%s]\n"), name);
1965*7304104dSAndroid Build Coastguard Worker 	  break;
1966*7304104dSAndroid Build Coastguard Worker 
1967*7304104dSAndroid Build Coastguard Worker 	case DT_RPATH:
1968*7304104dSAndroid Build Coastguard Worker 	  printf (_("Library rpath: [%s]\n"), name);
1969*7304104dSAndroid Build Coastguard Worker 	  break;
1970*7304104dSAndroid Build Coastguard Worker 
1971*7304104dSAndroid Build Coastguard Worker 	case DT_RUNPATH:
1972*7304104dSAndroid Build Coastguard Worker 	  printf (_("Library runpath: [%s]\n"), name);
1973*7304104dSAndroid Build Coastguard Worker 	  break;
1974*7304104dSAndroid Build Coastguard Worker 
1975*7304104dSAndroid Build Coastguard Worker 	case DT_PLTRELSZ:
1976*7304104dSAndroid Build Coastguard Worker 	case DT_RELASZ:
1977*7304104dSAndroid Build Coastguard Worker 	case DT_STRSZ:
1978*7304104dSAndroid Build Coastguard Worker 	case DT_RELSZ:
1979*7304104dSAndroid Build Coastguard Worker 	case DT_RELRSZ:
1980*7304104dSAndroid Build Coastguard Worker 	case DT_RELAENT:
1981*7304104dSAndroid Build Coastguard Worker 	case DT_SYMENT:
1982*7304104dSAndroid Build Coastguard Worker 	case DT_RELENT:
1983*7304104dSAndroid Build Coastguard Worker 	case DT_RELRENT:
1984*7304104dSAndroid Build Coastguard Worker 	case DT_PLTPADSZ:
1985*7304104dSAndroid Build Coastguard Worker 	case DT_MOVEENT:
1986*7304104dSAndroid Build Coastguard Worker 	case DT_MOVESZ:
1987*7304104dSAndroid Build Coastguard Worker 	case DT_INIT_ARRAYSZ:
1988*7304104dSAndroid Build Coastguard Worker 	case DT_FINI_ARRAYSZ:
1989*7304104dSAndroid Build Coastguard Worker 	case DT_SYMINSZ:
1990*7304104dSAndroid Build Coastguard Worker 	case DT_SYMINENT:
1991*7304104dSAndroid Build Coastguard Worker 	case DT_GNU_CONFLICTSZ:
1992*7304104dSAndroid Build Coastguard Worker 	case DT_GNU_LIBLISTSZ:
1993*7304104dSAndroid Build Coastguard Worker 	  printf (_("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
1994*7304104dSAndroid Build Coastguard Worker 	  break;
1995*7304104dSAndroid Build Coastguard Worker 
1996*7304104dSAndroid Build Coastguard Worker 	case DT_VERDEFNUM:
1997*7304104dSAndroid Build Coastguard Worker 	case DT_VERNEEDNUM:
1998*7304104dSAndroid Build Coastguard Worker 	case DT_RELACOUNT:
1999*7304104dSAndroid Build Coastguard Worker 	case DT_RELCOUNT:
2000*7304104dSAndroid Build Coastguard Worker 	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
2001*7304104dSAndroid Build Coastguard Worker 	  break;
2002*7304104dSAndroid Build Coastguard Worker 
2003*7304104dSAndroid Build Coastguard Worker 	case DT_PLTREL:;
2004*7304104dSAndroid Build Coastguard Worker 	  const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
2005*7304104dSAndroid Build Coastguard Worker 						      NULL, 0);
2006*7304104dSAndroid Build Coastguard Worker 	  puts (tagname ?: "???");
2007*7304104dSAndroid Build Coastguard Worker 	  break;
2008*7304104dSAndroid Build Coastguard Worker 
2009*7304104dSAndroid Build Coastguard Worker 	case DT_FLAGS:
2010*7304104dSAndroid Build Coastguard Worker 	  print_dt_flags (class, dyn->d_un.d_val);
2011*7304104dSAndroid Build Coastguard Worker 	  break;
2012*7304104dSAndroid Build Coastguard Worker 
2013*7304104dSAndroid Build Coastguard Worker 	case DT_FLAGS_1:
2014*7304104dSAndroid Build Coastguard Worker 	  print_dt_flags_1 (class, dyn->d_un.d_val);
2015*7304104dSAndroid Build Coastguard Worker 	  break;
2016*7304104dSAndroid Build Coastguard Worker 
2017*7304104dSAndroid Build Coastguard Worker 	case DT_FEATURE_1:
2018*7304104dSAndroid Build Coastguard Worker 	  print_dt_feature_1 (class, dyn->d_un.d_val);
2019*7304104dSAndroid Build Coastguard Worker 	  break;
2020*7304104dSAndroid Build Coastguard Worker 
2021*7304104dSAndroid Build Coastguard Worker 	case DT_POSFLAG_1:
2022*7304104dSAndroid Build Coastguard Worker 	  print_dt_posflag_1 (class, dyn->d_un.d_val);
2023*7304104dSAndroid Build Coastguard Worker 	  break;
2024*7304104dSAndroid Build Coastguard Worker 
2025*7304104dSAndroid Build Coastguard Worker 	default:
2026*7304104dSAndroid Build Coastguard Worker 	  printf ("%#0*" PRIx64 "\n",
2027*7304104dSAndroid Build Coastguard Worker 		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
2028*7304104dSAndroid Build Coastguard Worker 	  break;
2029*7304104dSAndroid Build Coastguard Worker 	}
2030*7304104dSAndroid Build Coastguard Worker     }
2031*7304104dSAndroid Build Coastguard Worker }
2032*7304104dSAndroid Build Coastguard Worker 
2033*7304104dSAndroid Build Coastguard Worker 
2034*7304104dSAndroid Build Coastguard Worker /* Print the dynamic segment.  */
2035*7304104dSAndroid Build Coastguard Worker static void
print_dynamic(Ebl * ebl)2036*7304104dSAndroid Build Coastguard Worker print_dynamic (Ebl *ebl)
2037*7304104dSAndroid Build Coastguard Worker {
2038*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < phnum; ++i)
2039*7304104dSAndroid Build Coastguard Worker     {
2040*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
2041*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
2042*7304104dSAndroid Build Coastguard Worker 
2043*7304104dSAndroid Build Coastguard Worker       if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
2044*7304104dSAndroid Build Coastguard Worker 	{
2045*7304104dSAndroid Build Coastguard Worker 	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
2046*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr shdr_mem;
2047*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2048*7304104dSAndroid Build Coastguard Worker 	  if ((use_dynamic_segment && phdr != NULL)
2049*7304104dSAndroid Build Coastguard Worker 	      || (shdr != NULL && shdr->sh_type == SHT_DYNAMIC))
2050*7304104dSAndroid Build Coastguard Worker 	    handle_dynamic (ebl, scn, shdr, phdr);
2051*7304104dSAndroid Build Coastguard Worker 	  break;
2052*7304104dSAndroid Build Coastguard Worker 	}
2053*7304104dSAndroid Build Coastguard Worker     }
2054*7304104dSAndroid Build Coastguard Worker }
2055*7304104dSAndroid Build Coastguard Worker 
2056*7304104dSAndroid Build Coastguard Worker 
2057*7304104dSAndroid Build Coastguard Worker /* Print relocations.  */
2058*7304104dSAndroid Build Coastguard Worker static void
print_relocs(Ebl * ebl,Dwfl_Module * mod,GElf_Ehdr * ehdr)2059*7304104dSAndroid Build Coastguard Worker print_relocs (Ebl *ebl, Dwfl_Module *mod, GElf_Ehdr *ehdr)
2060*7304104dSAndroid Build Coastguard Worker {
2061*7304104dSAndroid Build Coastguard Worker   /* Find all relocation sections and handle them.  */
2062*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
2063*7304104dSAndroid Build Coastguard Worker 
2064*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2065*7304104dSAndroid Build Coastguard Worker     {
2066*7304104dSAndroid Build Coastguard Worker        /* Handle the section if it is a symbol table.  */
2067*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
2068*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2069*7304104dSAndroid Build Coastguard Worker 
2070*7304104dSAndroid Build Coastguard Worker       if (likely (shdr != NULL))
2071*7304104dSAndroid Build Coastguard Worker 	{
2072*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_type == SHT_REL)
2073*7304104dSAndroid Build Coastguard Worker 	    handle_relocs_rel (ebl, ehdr, scn, shdr);
2074*7304104dSAndroid Build Coastguard Worker 	  else if (shdr->sh_type == SHT_RELA)
2075*7304104dSAndroid Build Coastguard Worker 	    handle_relocs_rela (ebl, ehdr, scn, shdr);
2076*7304104dSAndroid Build Coastguard Worker 	  else if (shdr->sh_type == SHT_RELR)
2077*7304104dSAndroid Build Coastguard Worker 	    handle_relocs_relr (ebl, mod, scn, shdr);
2078*7304104dSAndroid Build Coastguard Worker 	}
2079*7304104dSAndroid Build Coastguard Worker     }
2080*7304104dSAndroid Build Coastguard Worker }
2081*7304104dSAndroid Build Coastguard Worker 
2082*7304104dSAndroid Build Coastguard Worker 
2083*7304104dSAndroid Build Coastguard Worker /* Handle a relocation section.  */
2084*7304104dSAndroid Build Coastguard Worker static void
handle_relocs_rel(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)2085*7304104dSAndroid Build Coastguard Worker handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2086*7304104dSAndroid Build Coastguard Worker {
2087*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
2088*7304104dSAndroid Build Coastguard Worker   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
2089*7304104dSAndroid Build Coastguard Worker   int nentries = shdr->sh_size / sh_entsize;
2090*7304104dSAndroid Build Coastguard Worker 
2091*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
2092*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
2093*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
2094*7304104dSAndroid Build Coastguard Worker     return;
2095*7304104dSAndroid Build Coastguard Worker 
2096*7304104dSAndroid Build Coastguard Worker   /* Get the symbol table information.  */
2097*7304104dSAndroid Build Coastguard Worker   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2098*7304104dSAndroid Build Coastguard Worker   GElf_Shdr symshdr_mem;
2099*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2100*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = elf_getdata (symscn, NULL);
2101*7304104dSAndroid Build Coastguard Worker 
2102*7304104dSAndroid Build Coastguard Worker   /* Get the section header of the section the relocations are for.  */
2103*7304104dSAndroid Build Coastguard Worker   GElf_Shdr destshdr_mem;
2104*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
2105*7304104dSAndroid Build Coastguard Worker 				      &destshdr_mem);
2106*7304104dSAndroid Build Coastguard Worker 
2107*7304104dSAndroid Build Coastguard Worker   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
2108*7304104dSAndroid Build Coastguard Worker     {
2109*7304104dSAndroid Build Coastguard Worker       printf (_("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
2110*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_offset);
2111*7304104dSAndroid Build Coastguard Worker       return;
2112*7304104dSAndroid Build Coastguard Worker     }
2113*7304104dSAndroid Build Coastguard Worker 
2114*7304104dSAndroid Build Coastguard Worker   /* Search for the optional extended section index table.  */
2115*7304104dSAndroid Build Coastguard Worker   Elf_Data *xndxdata = NULL;
2116*7304104dSAndroid Build Coastguard Worker   int xndxscnidx = elf_scnshndx (scn);
2117*7304104dSAndroid Build Coastguard Worker   if (unlikely (xndxscnidx > 0))
2118*7304104dSAndroid Build Coastguard Worker     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
2119*7304104dSAndroid Build Coastguard Worker 
2120*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
2121*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
2122*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2123*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
2124*7304104dSAndroid Build Coastguard Worker 
2125*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_info != 0)
2126*7304104dSAndroid Build Coastguard Worker     printf (ngettext ("\
2127*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2128*7304104dSAndroid Build Coastguard Worker 		    "\
2129*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2130*7304104dSAndroid Build Coastguard Worker 		      nentries),
2131*7304104dSAndroid Build Coastguard Worker 	    elf_ndxscn (scn),
2132*7304104dSAndroid Build Coastguard Worker 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2133*7304104dSAndroid Build Coastguard Worker 	    (unsigned int) shdr->sh_info,
2134*7304104dSAndroid Build Coastguard Worker 	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
2135*7304104dSAndroid Build Coastguard Worker 	    shdr->sh_offset,
2136*7304104dSAndroid Build Coastguard Worker 	    nentries);
2137*7304104dSAndroid Build Coastguard Worker   else
2138*7304104dSAndroid Build Coastguard Worker     /* The .rel.dyn section does not refer to a specific section but
2139*7304104dSAndroid Build Coastguard Worker        instead of section index zero.  Do not try to print a section
2140*7304104dSAndroid Build Coastguard Worker        name.  */
2141*7304104dSAndroid Build Coastguard Worker     printf (ngettext ("\
2142*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2143*7304104dSAndroid Build Coastguard Worker 		    "\
2144*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2145*7304104dSAndroid Build Coastguard Worker 		      nentries),
2146*7304104dSAndroid Build Coastguard Worker 	    (unsigned int) elf_ndxscn (scn),
2147*7304104dSAndroid Build Coastguard Worker 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2148*7304104dSAndroid Build Coastguard Worker 	    shdr->sh_offset,
2149*7304104dSAndroid Build Coastguard Worker 	    nentries);
2150*7304104dSAndroid Build Coastguard Worker   fputs_unlocked (class == ELFCLASS32
2151*7304104dSAndroid Build Coastguard Worker 		  ? _("\
2152*7304104dSAndroid Build Coastguard Worker   Offset      Type                 Value       Name\n")
2153*7304104dSAndroid Build Coastguard Worker 		  : _("\
2154*7304104dSAndroid Build Coastguard Worker   Offset              Type                 Value               Name\n"),
2155*7304104dSAndroid Build Coastguard Worker 	 stdout);
2156*7304104dSAndroid Build Coastguard Worker 
2157*7304104dSAndroid Build Coastguard Worker   int is_statically_linked = 0;
2158*7304104dSAndroid Build Coastguard Worker   for (int cnt = 0; cnt < nentries; ++cnt)
2159*7304104dSAndroid Build Coastguard Worker     {
2160*7304104dSAndroid Build Coastguard Worker       GElf_Rel relmem;
2161*7304104dSAndroid Build Coastguard Worker       GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
2162*7304104dSAndroid Build Coastguard Worker       if (likely (rel != NULL))
2163*7304104dSAndroid Build Coastguard Worker 	{
2164*7304104dSAndroid Build Coastguard Worker 	  char buf[128];
2165*7304104dSAndroid Build Coastguard Worker 	  GElf_Sym symmem;
2166*7304104dSAndroid Build Coastguard Worker 	  Elf32_Word xndx;
2167*7304104dSAndroid Build Coastguard Worker 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2168*7304104dSAndroid Build Coastguard Worker 					    GELF_R_SYM (rel->r_info),
2169*7304104dSAndroid Build Coastguard Worker 					    &symmem, &xndx);
2170*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (sym == NULL))
2171*7304104dSAndroid Build Coastguard Worker 	    {
2172*7304104dSAndroid Build Coastguard Worker 	      /* As a special case we have to handle relocations in static
2173*7304104dSAndroid Build Coastguard Worker 		 executables.  This only happens for IRELATIVE relocations
2174*7304104dSAndroid Build Coastguard Worker 		 (so far).  There is no symbol table.  */
2175*7304104dSAndroid Build Coastguard Worker 	      if (is_statically_linked == 0)
2176*7304104dSAndroid Build Coastguard Worker 		{
2177*7304104dSAndroid Build Coastguard Worker 		  /* Find the program header and look for a PT_INTERP entry. */
2178*7304104dSAndroid Build Coastguard Worker 		  is_statically_linked = -1;
2179*7304104dSAndroid Build Coastguard Worker 		  if (ehdr->e_type == ET_EXEC)
2180*7304104dSAndroid Build Coastguard Worker 		    {
2181*7304104dSAndroid Build Coastguard Worker 		      is_statically_linked = 1;
2182*7304104dSAndroid Build Coastguard Worker 
2183*7304104dSAndroid Build Coastguard Worker 		      for (size_t inner = 0; inner < phnum; ++inner)
2184*7304104dSAndroid Build Coastguard Worker 			{
2185*7304104dSAndroid Build Coastguard Worker 			  GElf_Phdr phdr_mem;
2186*7304104dSAndroid Build Coastguard Worker 			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2187*7304104dSAndroid Build Coastguard Worker 							  &phdr_mem);
2188*7304104dSAndroid Build Coastguard Worker 			  if (phdr != NULL && phdr->p_type == PT_INTERP)
2189*7304104dSAndroid Build Coastguard Worker 			    {
2190*7304104dSAndroid Build Coastguard Worker 			      is_statically_linked = -1;
2191*7304104dSAndroid Build Coastguard Worker 			      break;
2192*7304104dSAndroid Build Coastguard Worker 			    }
2193*7304104dSAndroid Build Coastguard Worker 			}
2194*7304104dSAndroid Build Coastguard Worker 		    }
2195*7304104dSAndroid Build Coastguard Worker 		}
2196*7304104dSAndroid Build Coastguard Worker 
2197*7304104dSAndroid Build Coastguard Worker 	      if (is_statically_linked > 0 && shdr->sh_link == 0)
2198*7304104dSAndroid Build Coastguard Worker 		printf ("\
2199*7304104dSAndroid Build Coastguard Worker   %#0*" PRIx64 "  %-20s %*s  %s\n",
2200*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2201*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2202*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2203*7304104dSAndroid Build Coastguard Worker 			   information.  */
2204*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2205*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2206*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2207*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, "",
2208*7304104dSAndroid Build Coastguard Worker 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2209*7304104dSAndroid Build Coastguard Worker 	      else
2210*7304104dSAndroid Build Coastguard Worker 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
2211*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2212*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2213*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2214*7304104dSAndroid Build Coastguard Worker 			   information.  */
2215*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2216*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2217*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2218*7304104dSAndroid Build Coastguard Worker 			_("INVALID SYMBOL"),
2219*7304104dSAndroid Build Coastguard Worker 			(long int) GELF_R_SYM (rel->r_info));
2220*7304104dSAndroid Build Coastguard Worker 	    }
2221*7304104dSAndroid Build Coastguard Worker 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2222*7304104dSAndroid Build Coastguard Worker 	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
2223*7304104dSAndroid Build Coastguard Worker 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2224*7304104dSAndroid Build Coastguard Worker 		    likely (ebl_reloc_type_check (ebl,
2225*7304104dSAndroid Build Coastguard Worker 						  GELF_R_TYPE (rel->r_info)))
2226*7304104dSAndroid Build Coastguard Worker 		    /* Avoid the leading R_ which isn't carrying any
2227*7304104dSAndroid Build Coastguard Worker 		       information.  */
2228*7304104dSAndroid Build Coastguard Worker 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2229*7304104dSAndroid Build Coastguard Worker 					   buf, sizeof (buf)) + 2
2230*7304104dSAndroid Build Coastguard Worker 		    : _("<INVALID RELOC>"),
2231*7304104dSAndroid Build Coastguard Worker 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
2232*7304104dSAndroid Build Coastguard Worker 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2233*7304104dSAndroid Build Coastguard Worker 	  else
2234*7304104dSAndroid Build Coastguard Worker 	    {
2235*7304104dSAndroid Build Coastguard Worker 	      /* This is a relocation against a STT_SECTION symbol.  */
2236*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr secshdr_mem;
2237*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr *secshdr;
2238*7304104dSAndroid Build Coastguard Worker 	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2239*7304104dSAndroid Build Coastguard Worker 						  sym->st_shndx == SHN_XINDEX
2240*7304104dSAndroid Build Coastguard Worker 						  ? xndx : sym->st_shndx),
2241*7304104dSAndroid Build Coastguard Worker 				      &secshdr_mem);
2242*7304104dSAndroid Build Coastguard Worker 
2243*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (secshdr == NULL))
2244*7304104dSAndroid Build Coastguard Worker 		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
2245*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2246*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2247*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2248*7304104dSAndroid Build Coastguard Worker 			   information.  */
2249*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2250*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2251*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2252*7304104dSAndroid Build Coastguard Worker 			_("INVALID SECTION"),
2253*7304104dSAndroid Build Coastguard Worker 			(long int) (sym->st_shndx == SHN_XINDEX
2254*7304104dSAndroid Build Coastguard Worker 				    ? xndx : sym->st_shndx));
2255*7304104dSAndroid Build Coastguard Worker 	      else
2256*7304104dSAndroid Build Coastguard Worker 		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
2257*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2258*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2259*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2260*7304104dSAndroid Build Coastguard Worker 			   information.  */
2261*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2262*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2263*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2264*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
2265*7304104dSAndroid Build Coastguard Worker 			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2266*7304104dSAndroid Build Coastguard Worker 	    }
2267*7304104dSAndroid Build Coastguard Worker 	}
2268*7304104dSAndroid Build Coastguard Worker     }
2269*7304104dSAndroid Build Coastguard Worker }
2270*7304104dSAndroid Build Coastguard Worker 
2271*7304104dSAndroid Build Coastguard Worker 
2272*7304104dSAndroid Build Coastguard Worker /* Handle a relocation section.  */
2273*7304104dSAndroid Build Coastguard Worker static void
handle_relocs_rela(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr)2274*7304104dSAndroid Build Coastguard Worker handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
2275*7304104dSAndroid Build Coastguard Worker {
2276*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
2277*7304104dSAndroid Build Coastguard Worker   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
2278*7304104dSAndroid Build Coastguard Worker   int nentries = shdr->sh_size / sh_entsize;
2279*7304104dSAndroid Build Coastguard Worker 
2280*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
2281*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
2282*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
2283*7304104dSAndroid Build Coastguard Worker     return;
2284*7304104dSAndroid Build Coastguard Worker 
2285*7304104dSAndroid Build Coastguard Worker   /* Get the symbol table information.  */
2286*7304104dSAndroid Build Coastguard Worker   Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
2287*7304104dSAndroid Build Coastguard Worker   GElf_Shdr symshdr_mem;
2288*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
2289*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = elf_getdata (symscn, NULL);
2290*7304104dSAndroid Build Coastguard Worker 
2291*7304104dSAndroid Build Coastguard Worker   /* Get the section header of the section the relocations are for.  */
2292*7304104dSAndroid Build Coastguard Worker   GElf_Shdr destshdr_mem;
2293*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
2294*7304104dSAndroid Build Coastguard Worker 				      &destshdr_mem);
2295*7304104dSAndroid Build Coastguard Worker 
2296*7304104dSAndroid Build Coastguard Worker   if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
2297*7304104dSAndroid Build Coastguard Worker     {
2298*7304104dSAndroid Build Coastguard Worker       printf (_("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
2299*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_offset);
2300*7304104dSAndroid Build Coastguard Worker       return;
2301*7304104dSAndroid Build Coastguard Worker     }
2302*7304104dSAndroid Build Coastguard Worker 
2303*7304104dSAndroid Build Coastguard Worker   /* Search for the optional extended section index table.  */
2304*7304104dSAndroid Build Coastguard Worker   Elf_Data *xndxdata = NULL;
2305*7304104dSAndroid Build Coastguard Worker   int xndxscnidx = elf_scnshndx (scn);
2306*7304104dSAndroid Build Coastguard Worker   if (unlikely (xndxscnidx > 0))
2307*7304104dSAndroid Build Coastguard Worker     xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
2308*7304104dSAndroid Build Coastguard Worker 
2309*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
2310*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
2311*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2312*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
2313*7304104dSAndroid Build Coastguard Worker 
2314*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_info != 0)
2315*7304104dSAndroid Build Coastguard Worker     printf (ngettext ("\
2316*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2317*7304104dSAndroid Build Coastguard Worker 		    "\
2318*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2319*7304104dSAndroid Build Coastguard Worker 		    nentries),
2320*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn),
2321*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2322*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) shdr->sh_info,
2323*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
2324*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_offset,
2325*7304104dSAndroid Build Coastguard Worker 	  nentries);
2326*7304104dSAndroid Build Coastguard Worker   else
2327*7304104dSAndroid Build Coastguard Worker     /* The .rela.dyn section does not refer to a specific section but
2328*7304104dSAndroid Build Coastguard Worker        instead of section index zero.  Do not try to print a section
2329*7304104dSAndroid Build Coastguard Worker        name.  */
2330*7304104dSAndroid Build Coastguard Worker     printf (ngettext ("\
2331*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2332*7304104dSAndroid Build Coastguard Worker 		    "\
2333*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2334*7304104dSAndroid Build Coastguard Worker 		      nentries),
2335*7304104dSAndroid Build Coastguard Worker 	    (unsigned int) elf_ndxscn (scn),
2336*7304104dSAndroid Build Coastguard Worker 	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2337*7304104dSAndroid Build Coastguard Worker 	    shdr->sh_offset,
2338*7304104dSAndroid Build Coastguard Worker 	    nentries);
2339*7304104dSAndroid Build Coastguard Worker   fputs_unlocked (class == ELFCLASS32
2340*7304104dSAndroid Build Coastguard Worker 		  ? _("\
2341*7304104dSAndroid Build Coastguard Worker   Offset      Type            Value       Addend Name\n")
2342*7304104dSAndroid Build Coastguard Worker 		  : _("\
2343*7304104dSAndroid Build Coastguard Worker   Offset              Type            Value               Addend Name\n"),
2344*7304104dSAndroid Build Coastguard Worker 		  stdout);
2345*7304104dSAndroid Build Coastguard Worker 
2346*7304104dSAndroid Build Coastguard Worker   int is_statically_linked = 0;
2347*7304104dSAndroid Build Coastguard Worker   for (int cnt = 0; cnt < nentries; ++cnt)
2348*7304104dSAndroid Build Coastguard Worker     {
2349*7304104dSAndroid Build Coastguard Worker       GElf_Rela relmem;
2350*7304104dSAndroid Build Coastguard Worker       GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
2351*7304104dSAndroid Build Coastguard Worker       if (likely (rel != NULL))
2352*7304104dSAndroid Build Coastguard Worker 	{
2353*7304104dSAndroid Build Coastguard Worker 	  char buf[64];
2354*7304104dSAndroid Build Coastguard Worker 	  GElf_Sym symmem;
2355*7304104dSAndroid Build Coastguard Worker 	  Elf32_Word xndx;
2356*7304104dSAndroid Build Coastguard Worker 	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
2357*7304104dSAndroid Build Coastguard Worker 					    GELF_R_SYM (rel->r_info),
2358*7304104dSAndroid Build Coastguard Worker 					    &symmem, &xndx);
2359*7304104dSAndroid Build Coastguard Worker 
2360*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (sym == NULL))
2361*7304104dSAndroid Build Coastguard Worker 	    {
2362*7304104dSAndroid Build Coastguard Worker 	      /* As a special case we have to handle relocations in static
2363*7304104dSAndroid Build Coastguard Worker 		 executables.  This only happens for IRELATIVE relocations
2364*7304104dSAndroid Build Coastguard Worker 		 (so far).  There is no symbol table.  */
2365*7304104dSAndroid Build Coastguard Worker 	      if (is_statically_linked == 0)
2366*7304104dSAndroid Build Coastguard Worker 		{
2367*7304104dSAndroid Build Coastguard Worker 		  /* Find the program header and look for a PT_INTERP entry. */
2368*7304104dSAndroid Build Coastguard Worker 		  is_statically_linked = -1;
2369*7304104dSAndroid Build Coastguard Worker 		  if (ehdr->e_type == ET_EXEC)
2370*7304104dSAndroid Build Coastguard Worker 		    {
2371*7304104dSAndroid Build Coastguard Worker 		      is_statically_linked = 1;
2372*7304104dSAndroid Build Coastguard Worker 
2373*7304104dSAndroid Build Coastguard Worker 		      for (size_t inner = 0; inner < phnum; ++inner)
2374*7304104dSAndroid Build Coastguard Worker 			{
2375*7304104dSAndroid Build Coastguard Worker 			  GElf_Phdr phdr_mem;
2376*7304104dSAndroid Build Coastguard Worker 			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
2377*7304104dSAndroid Build Coastguard Worker 							  &phdr_mem);
2378*7304104dSAndroid Build Coastguard Worker 			  if (phdr != NULL && phdr->p_type == PT_INTERP)
2379*7304104dSAndroid Build Coastguard Worker 			    {
2380*7304104dSAndroid Build Coastguard Worker 			      is_statically_linked = -1;
2381*7304104dSAndroid Build Coastguard Worker 			      break;
2382*7304104dSAndroid Build Coastguard Worker 			    }
2383*7304104dSAndroid Build Coastguard Worker 			}
2384*7304104dSAndroid Build Coastguard Worker 		    }
2385*7304104dSAndroid Build Coastguard Worker 		}
2386*7304104dSAndroid Build Coastguard Worker 
2387*7304104dSAndroid Build Coastguard Worker 	      if (is_statically_linked > 0 && shdr->sh_link == 0)
2388*7304104dSAndroid Build Coastguard Worker 		printf ("\
2389*7304104dSAndroid Build Coastguard Worker   %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
2390*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2391*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2392*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2393*7304104dSAndroid Build Coastguard Worker 			   information.  */
2394*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2395*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2396*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2397*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, "",
2398*7304104dSAndroid Build Coastguard Worker 			rel->r_addend,
2399*7304104dSAndroid Build Coastguard Worker 			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
2400*7304104dSAndroid Build Coastguard Worker 	      else
2401*7304104dSAndroid Build Coastguard Worker 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
2402*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2403*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2404*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2405*7304104dSAndroid Build Coastguard Worker 			   information.  */
2406*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2407*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2408*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2409*7304104dSAndroid Build Coastguard Worker 			_("INVALID SYMBOL"),
2410*7304104dSAndroid Build Coastguard Worker 			(long int) GELF_R_SYM (rel->r_info));
2411*7304104dSAndroid Build Coastguard Worker 	    }
2412*7304104dSAndroid Build Coastguard Worker 	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
2413*7304104dSAndroid Build Coastguard Worker 	    printf ("\
2414*7304104dSAndroid Build Coastguard Worker   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
2415*7304104dSAndroid Build Coastguard Worker 		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2416*7304104dSAndroid Build Coastguard Worker 		    likely (ebl_reloc_type_check (ebl,
2417*7304104dSAndroid Build Coastguard Worker 						  GELF_R_TYPE (rel->r_info)))
2418*7304104dSAndroid Build Coastguard Worker 		    /* Avoid the leading R_ which isn't carrying any
2419*7304104dSAndroid Build Coastguard Worker 		       information.  */
2420*7304104dSAndroid Build Coastguard Worker 		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2421*7304104dSAndroid Build Coastguard Worker 					   buf, sizeof (buf)) + 2
2422*7304104dSAndroid Build Coastguard Worker 		    : _("<INVALID RELOC>"),
2423*7304104dSAndroid Build Coastguard Worker 		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
2424*7304104dSAndroid Build Coastguard Worker 		    rel->r_addend,
2425*7304104dSAndroid Build Coastguard Worker 		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
2426*7304104dSAndroid Build Coastguard Worker 	  else
2427*7304104dSAndroid Build Coastguard Worker 	    {
2428*7304104dSAndroid Build Coastguard Worker 	      /* This is a relocation against a STT_SECTION symbol.  */
2429*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr secshdr_mem;
2430*7304104dSAndroid Build Coastguard Worker 	      GElf_Shdr *secshdr;
2431*7304104dSAndroid Build Coastguard Worker 	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
2432*7304104dSAndroid Build Coastguard Worker 						  sym->st_shndx == SHN_XINDEX
2433*7304104dSAndroid Build Coastguard Worker 						  ? xndx : sym->st_shndx),
2434*7304104dSAndroid Build Coastguard Worker 				      &secshdr_mem);
2435*7304104dSAndroid Build Coastguard Worker 
2436*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (secshdr == NULL))
2437*7304104dSAndroid Build Coastguard Worker 		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
2438*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2439*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2440*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2441*7304104dSAndroid Build Coastguard Worker 			   information.  */
2442*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2443*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2444*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2445*7304104dSAndroid Build Coastguard Worker 			_("INVALID SECTION"),
2446*7304104dSAndroid Build Coastguard Worker 			(long int) (sym->st_shndx == SHN_XINDEX
2447*7304104dSAndroid Build Coastguard Worker 				    ? xndx : sym->st_shndx));
2448*7304104dSAndroid Build Coastguard Worker 	      else
2449*7304104dSAndroid Build Coastguard Worker 		printf ("\
2450*7304104dSAndroid Build Coastguard Worker   %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
2451*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
2452*7304104dSAndroid Build Coastguard Worker 			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
2453*7304104dSAndroid Build Coastguard Worker 			/* Avoid the leading R_ which isn't carrying any
2454*7304104dSAndroid Build Coastguard Worker 			   information.  */
2455*7304104dSAndroid Build Coastguard Worker 			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
2456*7304104dSAndroid Build Coastguard Worker 					       buf, sizeof (buf)) + 2
2457*7304104dSAndroid Build Coastguard Worker 			: _("<INVALID RELOC>"),
2458*7304104dSAndroid Build Coastguard Worker 			class == ELFCLASS32 ? 10 : 18, sym->st_value,
2459*7304104dSAndroid Build Coastguard Worker 			rel->r_addend,
2460*7304104dSAndroid Build Coastguard Worker 			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
2461*7304104dSAndroid Build Coastguard Worker 	    }
2462*7304104dSAndroid Build Coastguard Worker 	}
2463*7304104dSAndroid Build Coastguard Worker     }
2464*7304104dSAndroid Build Coastguard Worker }
2465*7304104dSAndroid Build Coastguard Worker 
2466*7304104dSAndroid Build Coastguard Worker /* Handle a relocation section.  */
2467*7304104dSAndroid Build Coastguard Worker static void
handle_relocs_relr(Ebl * ebl,Dwfl_Module * mod,Elf_Scn * scn,GElf_Shdr * shdr)2468*7304104dSAndroid Build Coastguard Worker handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn, GElf_Shdr *shdr)
2469*7304104dSAndroid Build Coastguard Worker {
2470*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
2471*7304104dSAndroid Build Coastguard Worker   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELR, 1, EV_CURRENT);
2472*7304104dSAndroid Build Coastguard Worker   int nentries = shdr->sh_size / sh_entsize;
2473*7304104dSAndroid Build Coastguard Worker 
2474*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
2475*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
2476*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
2477*7304104dSAndroid Build Coastguard Worker     return;
2478*7304104dSAndroid Build Coastguard Worker 
2479*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
2480*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
2481*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2482*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
2483*7304104dSAndroid Build Coastguard Worker 
2484*7304104dSAndroid Build Coastguard Worker   /* A .relr.dyn section does not refer to a specific section.  */
2485*7304104dSAndroid Build Coastguard Worker   printf (ngettext ("\
2486*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
2487*7304104dSAndroid Build Coastguard Worker 		    "\
2488*7304104dSAndroid Build Coastguard Worker \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
2489*7304104dSAndroid Build Coastguard Worker 		    nentries),
2490*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) elf_ndxscn (scn),
2491*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
2492*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_offset,
2493*7304104dSAndroid Build Coastguard Worker 	  nentries);
2494*7304104dSAndroid Build Coastguard Worker 
2495*7304104dSAndroid Build Coastguard Worker   if (class == ELFCLASS32)
2496*7304104dSAndroid Build Coastguard Worker     {
2497*7304104dSAndroid Build Coastguard Worker       uint32_t base = 0;
2498*7304104dSAndroid Build Coastguard Worker       for (int cnt = 0; cnt < nentries; ++cnt)
2499*7304104dSAndroid Build Coastguard Worker 	{
2500*7304104dSAndroid Build Coastguard Worker 	  Elf32_Word *words = data->d_buf;
2501*7304104dSAndroid Build Coastguard Worker 	  Elf32_Word entry = words[cnt];
2502*7304104dSAndroid Build Coastguard Worker 
2503*7304104dSAndroid Build Coastguard Worker 	  /* Just the raw entries?  */
2504*7304104dSAndroid Build Coastguard Worker 	  if (print_unresolved_addresses)
2505*7304104dSAndroid Build Coastguard Worker             printf ("  %#010" PRIx32 "%s\n", entry,
2506*7304104dSAndroid Build Coastguard Worker                     (entry & 1) == 0 ? " *" : "");
2507*7304104dSAndroid Build Coastguard Worker 	  else
2508*7304104dSAndroid Build Coastguard Worker 	    {
2509*7304104dSAndroid Build Coastguard Worker 	      /* A real address, also sets base.  */
2510*7304104dSAndroid Build Coastguard Worker 	      if ((entry & 1) == 0)
2511*7304104dSAndroid Build Coastguard Worker 		{
2512*7304104dSAndroid Build Coastguard Worker 		  printf ("  ");
2513*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (mod, 4, entry, entry);
2514*7304104dSAndroid Build Coastguard Worker 		  printf (" *\n");
2515*7304104dSAndroid Build Coastguard Worker 
2516*7304104dSAndroid Build Coastguard Worker 		  base = entry + 4;
2517*7304104dSAndroid Build Coastguard Worker 		}
2518*7304104dSAndroid Build Coastguard Worker 	      else
2519*7304104dSAndroid Build Coastguard Worker 		{
2520*7304104dSAndroid Build Coastguard Worker 		  /* Untangle address from base and bits.  */
2521*7304104dSAndroid Build Coastguard Worker 		  uint32_t addr;
2522*7304104dSAndroid Build Coastguard Worker 		  for (addr = base; (entry >>= 1) != 0; addr += 4)
2523*7304104dSAndroid Build Coastguard Worker 		    if ((entry & 1) != 0)
2524*7304104dSAndroid Build Coastguard Worker 		      {
2525*7304104dSAndroid Build Coastguard Worker 			printf ("  ");
2526*7304104dSAndroid Build Coastguard Worker 			print_dwarf_addr (mod, 4, addr, addr);
2527*7304104dSAndroid Build Coastguard Worker 			printf ("\n");
2528*7304104dSAndroid Build Coastguard Worker 		      }
2529*7304104dSAndroid Build Coastguard Worker 		  base += 4 * (4 * 8 - 1);
2530*7304104dSAndroid Build Coastguard Worker 		}
2531*7304104dSAndroid Build Coastguard Worker 	    }
2532*7304104dSAndroid Build Coastguard Worker 	}
2533*7304104dSAndroid Build Coastguard Worker     }
2534*7304104dSAndroid Build Coastguard Worker   else
2535*7304104dSAndroid Build Coastguard Worker     {
2536*7304104dSAndroid Build Coastguard Worker       uint64_t base = 0;
2537*7304104dSAndroid Build Coastguard Worker       for (int cnt = 0; cnt < nentries; ++cnt)
2538*7304104dSAndroid Build Coastguard Worker 	{
2539*7304104dSAndroid Build Coastguard Worker 	  Elf64_Xword *xwords = data->d_buf;
2540*7304104dSAndroid Build Coastguard Worker 	  Elf64_Xword entry = xwords[cnt];
2541*7304104dSAndroid Build Coastguard Worker 
2542*7304104dSAndroid Build Coastguard Worker 	  /* Just the raw entries?  */
2543*7304104dSAndroid Build Coastguard Worker 	  if (print_unresolved_addresses)
2544*7304104dSAndroid Build Coastguard Worker 	    printf ("  %#018" PRIx64 "%s\n", entry,
2545*7304104dSAndroid Build Coastguard Worker 		    (entry & 1) == 0 ? " *" : "");
2546*7304104dSAndroid Build Coastguard Worker 	  else
2547*7304104dSAndroid Build Coastguard Worker 	    {
2548*7304104dSAndroid Build Coastguard Worker 	      /* A real address, also sets base.  */
2549*7304104dSAndroid Build Coastguard Worker 	      if ((entry & 1) == 0)
2550*7304104dSAndroid Build Coastguard Worker 		{
2551*7304104dSAndroid Build Coastguard Worker 		  printf ("  ");
2552*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (mod, 8, entry, entry);
2553*7304104dSAndroid Build Coastguard Worker 		  printf (" *\n");
2554*7304104dSAndroid Build Coastguard Worker 
2555*7304104dSAndroid Build Coastguard Worker 		  base = entry + 8;
2556*7304104dSAndroid Build Coastguard Worker 		}
2557*7304104dSAndroid Build Coastguard Worker 	      else
2558*7304104dSAndroid Build Coastguard Worker 		{
2559*7304104dSAndroid Build Coastguard Worker 		  /* Untangle address from base and bits.  */
2560*7304104dSAndroid Build Coastguard Worker 		  uint64_t addr;
2561*7304104dSAndroid Build Coastguard Worker 		  for (addr = base; (entry >>= 1) != 0; addr += 8)
2562*7304104dSAndroid Build Coastguard Worker 		    if ((entry & 1) != 0)
2563*7304104dSAndroid Build Coastguard Worker 		      {
2564*7304104dSAndroid Build Coastguard Worker 			printf ("  ");
2565*7304104dSAndroid Build Coastguard Worker 			print_dwarf_addr (mod, 8, addr, addr);
2566*7304104dSAndroid Build Coastguard Worker 			printf ("\n");
2567*7304104dSAndroid Build Coastguard Worker 		      }
2568*7304104dSAndroid Build Coastguard Worker 		  base += 8 * (8 * 8 - 1);
2569*7304104dSAndroid Build Coastguard Worker 		}
2570*7304104dSAndroid Build Coastguard Worker 	    }
2571*7304104dSAndroid Build Coastguard Worker 	}
2572*7304104dSAndroid Build Coastguard Worker     }
2573*7304104dSAndroid Build Coastguard Worker }
2574*7304104dSAndroid Build Coastguard Worker 
2575*7304104dSAndroid Build Coastguard Worker /* Print the program header.  Return true if a symtab is printed,
2576*7304104dSAndroid Build Coastguard Worker    false otherwise.  */
2577*7304104dSAndroid Build Coastguard Worker static bool
print_symtab(Ebl * ebl,int type)2578*7304104dSAndroid Build Coastguard Worker print_symtab (Ebl *ebl, int type)
2579*7304104dSAndroid Build Coastguard Worker {
2580*7304104dSAndroid Build Coastguard Worker   /* Use the dynamic section info to display symbol tables.  */
2581*7304104dSAndroid Build Coastguard Worker   if (use_dynamic_segment && type == SHT_DYNSYM)
2582*7304104dSAndroid Build Coastguard Worker     return handle_dynamic_symtab(ebl);
2583*7304104dSAndroid Build Coastguard Worker 
2584*7304104dSAndroid Build Coastguard Worker   /* Find the symbol table(s).  For this we have to search through the
2585*7304104dSAndroid Build Coastguard Worker      section table.  */
2586*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
2587*7304104dSAndroid Build Coastguard Worker   bool symtab_printed = false;
2588*7304104dSAndroid Build Coastguard Worker 
2589*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
2590*7304104dSAndroid Build Coastguard Worker     {
2591*7304104dSAndroid Build Coastguard Worker       /* Handle the section if it is a symbol table.  */
2592*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
2593*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2594*7304104dSAndroid Build Coastguard Worker 
2595*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
2596*7304104dSAndroid Build Coastguard Worker 	{
2597*7304104dSAndroid Build Coastguard Worker 	  if (symbol_table_section != NULL)
2598*7304104dSAndroid Build Coastguard Worker 	    {
2599*7304104dSAndroid Build Coastguard Worker 	      /* Get the section header string table index.  */
2600*7304104dSAndroid Build Coastguard Worker 	      size_t shstrndx;
2601*7304104dSAndroid Build Coastguard Worker 	      const char *sname;
2602*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2603*7304104dSAndroid Build Coastguard Worker 		error_exit (0,
2604*7304104dSAndroid Build Coastguard Worker 			    _("cannot get section header string table index"));
2605*7304104dSAndroid Build Coastguard Worker 	      sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
2606*7304104dSAndroid Build Coastguard Worker 	      if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
2607*7304104dSAndroid Build Coastguard Worker 		continue;
2608*7304104dSAndroid Build Coastguard Worker 	    }
2609*7304104dSAndroid Build Coastguard Worker 
2610*7304104dSAndroid Build Coastguard Worker 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
2611*7304104dSAndroid Build Coastguard Worker 	    {
2612*7304104dSAndroid Build Coastguard Worker 	      if (elf_compress (scn, 0, 0) < 0)
2613*7304104dSAndroid Build Coastguard Worker 		printf ("WARNING: %s [%zd]\n",
2614*7304104dSAndroid Build Coastguard Worker 			_("Couldn't uncompress section"),
2615*7304104dSAndroid Build Coastguard Worker 			elf_ndxscn (scn));
2616*7304104dSAndroid Build Coastguard Worker 	      shdr = gelf_getshdr (scn, &shdr_mem);
2617*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (shdr == NULL))
2618*7304104dSAndroid Build Coastguard Worker 		error_exit (0,
2619*7304104dSAndroid Build Coastguard Worker 			    _("cannot get section [%zd] header: %s"),
2620*7304104dSAndroid Build Coastguard Worker 			    elf_ndxscn (scn), elf_errmsg (-1));
2621*7304104dSAndroid Build Coastguard Worker 	    }
2622*7304104dSAndroid Build Coastguard Worker 	  symtab_printed = handle_symtab (ebl, scn, shdr);
2623*7304104dSAndroid Build Coastguard Worker 	}
2624*7304104dSAndroid Build Coastguard Worker     }
2625*7304104dSAndroid Build Coastguard Worker 
2626*7304104dSAndroid Build Coastguard Worker   return symtab_printed;
2627*7304104dSAndroid Build Coastguard Worker }
2628*7304104dSAndroid Build Coastguard Worker 
2629*7304104dSAndroid Build Coastguard Worker 
2630*7304104dSAndroid Build Coastguard Worker static void
process_symtab(Ebl * ebl,unsigned int nsyms,Elf64_Word idx,Elf32_Word verneed_stridx,Elf32_Word verdef_stridx,Elf_Data * symdata,Elf_Data * versym_data,Elf_Data * symstr_data,Elf_Data * verneed_data,Elf_Data * verdef_data,Elf_Data * xndx_data)2631*7304104dSAndroid Build Coastguard Worker process_symtab (Ebl *ebl, unsigned int nsyms, Elf64_Word idx,
2632*7304104dSAndroid Build Coastguard Worker                 Elf32_Word verneed_stridx, Elf32_Word verdef_stridx,
2633*7304104dSAndroid Build Coastguard Worker                 Elf_Data *symdata, Elf_Data *versym_data,
2634*7304104dSAndroid Build Coastguard Worker                 Elf_Data *symstr_data, Elf_Data *verneed_data,
2635*7304104dSAndroid Build Coastguard Worker                 Elf_Data *verdef_data, Elf_Data *xndx_data)
2636*7304104dSAndroid Build Coastguard Worker {
2637*7304104dSAndroid Build Coastguard Worker   for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
2638*7304104dSAndroid Build Coastguard Worker     {
2639*7304104dSAndroid Build Coastguard Worker       char typebuf[64];
2640*7304104dSAndroid Build Coastguard Worker       char bindbuf[64];
2641*7304104dSAndroid Build Coastguard Worker       char scnbuf[64];
2642*7304104dSAndroid Build Coastguard Worker       Elf32_Word xndx;
2643*7304104dSAndroid Build Coastguard Worker       GElf_Sym sym_mem;
2644*7304104dSAndroid Build Coastguard Worker       GElf_Sym *sym
2645*7304104dSAndroid Build Coastguard Worker           = gelf_getsymshndx (symdata, xndx_data, cnt, &sym_mem, &xndx);
2646*7304104dSAndroid Build Coastguard Worker 
2647*7304104dSAndroid Build Coastguard Worker       if (unlikely (sym == NULL))
2648*7304104dSAndroid Build Coastguard Worker         continue;
2649*7304104dSAndroid Build Coastguard Worker 
2650*7304104dSAndroid Build Coastguard Worker       /* Determine the real section index.  */
2651*7304104dSAndroid Build Coastguard Worker       if (likely (sym->st_shndx != SHN_XINDEX))
2652*7304104dSAndroid Build Coastguard Worker         xndx = sym->st_shndx;
2653*7304104dSAndroid Build Coastguard Worker 
2654*7304104dSAndroid Build Coastguard Worker       printf (_ ("\
2655*7304104dSAndroid Build Coastguard Worker %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
2656*7304104dSAndroid Build Coastguard Worker               cnt, gelf_getclass (ebl->elf) == ELFCLASS32 ? 8 : 16,
2657*7304104dSAndroid Build Coastguard Worker               sym->st_value, sym->st_size,
2658*7304104dSAndroid Build Coastguard Worker               ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), typebuf,
2659*7304104dSAndroid Build Coastguard Worker                                     sizeof (typebuf)),
2660*7304104dSAndroid Build Coastguard Worker               ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
2661*7304104dSAndroid Build Coastguard Worker                                        bindbuf, sizeof (bindbuf)),
2662*7304104dSAndroid Build Coastguard Worker               get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
2663*7304104dSAndroid Build Coastguard Worker               ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
2664*7304104dSAndroid Build Coastguard Worker                                 sizeof (scnbuf), NULL, shnum),
2665*7304104dSAndroid Build Coastguard Worker               use_dynamic_segment == true
2666*7304104dSAndroid Build Coastguard Worker                   ? (char *)symstr_data->d_buf + sym->st_name
2667*7304104dSAndroid Build Coastguard Worker                   : elf_strptr (ebl->elf, idx, sym->st_name));
2668*7304104dSAndroid Build Coastguard Worker 
2669*7304104dSAndroid Build Coastguard Worker       if (versym_data != NULL)
2670*7304104dSAndroid Build Coastguard Worker         {
2671*7304104dSAndroid Build Coastguard Worker           /* Get the version information.  */
2672*7304104dSAndroid Build Coastguard Worker           GElf_Versym versym_mem;
2673*7304104dSAndroid Build Coastguard Worker           GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
2674*7304104dSAndroid Build Coastguard Worker 
2675*7304104dSAndroid Build Coastguard Worker           if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
2676*7304104dSAndroid Build Coastguard Worker             {
2677*7304104dSAndroid Build Coastguard Worker               bool is_nobits = false;
2678*7304104dSAndroid Build Coastguard Worker               bool check_def = xndx != SHN_UNDEF;
2679*7304104dSAndroid Build Coastguard Worker 
2680*7304104dSAndroid Build Coastguard Worker               if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
2681*7304104dSAndroid Build Coastguard Worker                 {
2682*7304104dSAndroid Build Coastguard Worker                   GElf_Shdr symshdr_mem;
2683*7304104dSAndroid Build Coastguard Worker                   GElf_Shdr *symshdr = gelf_getshdr (
2684*7304104dSAndroid Build Coastguard Worker                       elf_getscn (ebl->elf, xndx), &symshdr_mem);
2685*7304104dSAndroid Build Coastguard Worker 
2686*7304104dSAndroid Build Coastguard Worker                   is_nobits
2687*7304104dSAndroid Build Coastguard Worker                       = (symshdr != NULL && symshdr->sh_type == SHT_NOBITS);
2688*7304104dSAndroid Build Coastguard Worker                 }
2689*7304104dSAndroid Build Coastguard Worker 
2690*7304104dSAndroid Build Coastguard Worker               if (is_nobits || !check_def)
2691*7304104dSAndroid Build Coastguard Worker                 {
2692*7304104dSAndroid Build Coastguard Worker                   /* We must test both.  */
2693*7304104dSAndroid Build Coastguard Worker                   GElf_Vernaux vernaux_mem;
2694*7304104dSAndroid Build Coastguard Worker                   GElf_Vernaux *vernaux = NULL;
2695*7304104dSAndroid Build Coastguard Worker                   size_t vn_offset = 0;
2696*7304104dSAndroid Build Coastguard Worker 
2697*7304104dSAndroid Build Coastguard Worker                   GElf_Verneed verneed_mem;
2698*7304104dSAndroid Build Coastguard Worker                   GElf_Verneed *verneed
2699*7304104dSAndroid Build Coastguard Worker                       = gelf_getverneed (verneed_data, 0, &verneed_mem);
2700*7304104dSAndroid Build Coastguard Worker                   while (verneed != NULL)
2701*7304104dSAndroid Build Coastguard Worker                     {
2702*7304104dSAndroid Build Coastguard Worker                       size_t vna_offset = vn_offset;
2703*7304104dSAndroid Build Coastguard Worker 
2704*7304104dSAndroid Build Coastguard Worker                       vernaux = gelf_getvernaux (verneed_data,
2705*7304104dSAndroid Build Coastguard Worker                                                  vna_offset += verneed->vn_aux,
2706*7304104dSAndroid Build Coastguard Worker                                                  &vernaux_mem);
2707*7304104dSAndroid Build Coastguard Worker                       while (vernaux != NULL && vernaux->vna_other != *versym
2708*7304104dSAndroid Build Coastguard Worker                              && vernaux->vna_next != 0
2709*7304104dSAndroid Build Coastguard Worker                              && (verneed_data->d_size - vna_offset
2710*7304104dSAndroid Build Coastguard Worker                                  >= vernaux->vna_next))
2711*7304104dSAndroid Build Coastguard Worker                         {
2712*7304104dSAndroid Build Coastguard Worker                           /* Update the offset.  */
2713*7304104dSAndroid Build Coastguard Worker                           vna_offset += vernaux->vna_next;
2714*7304104dSAndroid Build Coastguard Worker 
2715*7304104dSAndroid Build Coastguard Worker                           vernaux = (vernaux->vna_next == 0
2716*7304104dSAndroid Build Coastguard Worker                                          ? NULL
2717*7304104dSAndroid Build Coastguard Worker                                          : gelf_getvernaux (verneed_data,
2718*7304104dSAndroid Build Coastguard Worker                                                             vna_offset,
2719*7304104dSAndroid Build Coastguard Worker                                                             &vernaux_mem));
2720*7304104dSAndroid Build Coastguard Worker                         }
2721*7304104dSAndroid Build Coastguard Worker 
2722*7304104dSAndroid Build Coastguard Worker                       /* Check whether we found the version.  */
2723*7304104dSAndroid Build Coastguard Worker                       if (vernaux != NULL && vernaux->vna_other == *versym)
2724*7304104dSAndroid Build Coastguard Worker                         /* Found it.  */
2725*7304104dSAndroid Build Coastguard Worker                         break;
2726*7304104dSAndroid Build Coastguard Worker 
2727*7304104dSAndroid Build Coastguard Worker                       if (verneed_data->d_size - vn_offset < verneed->vn_next)
2728*7304104dSAndroid Build Coastguard Worker                         break;
2729*7304104dSAndroid Build Coastguard Worker 
2730*7304104dSAndroid Build Coastguard Worker                       vn_offset += verneed->vn_next;
2731*7304104dSAndroid Build Coastguard Worker                       verneed
2732*7304104dSAndroid Build Coastguard Worker                           = (verneed->vn_next == 0
2733*7304104dSAndroid Build Coastguard Worker                                  ? NULL
2734*7304104dSAndroid Build Coastguard Worker                                  : gelf_getverneed (verneed_data, vn_offset,
2735*7304104dSAndroid Build Coastguard Worker                                                     &verneed_mem));
2736*7304104dSAndroid Build Coastguard Worker                     }
2737*7304104dSAndroid Build Coastguard Worker 
2738*7304104dSAndroid Build Coastguard Worker                   if (vernaux != NULL && vernaux->vna_other == *versym)
2739*7304104dSAndroid Build Coastguard Worker                     {
2740*7304104dSAndroid Build Coastguard Worker                       printf ("@%s (%u)",
2741*7304104dSAndroid Build Coastguard Worker                               use_dynamic_segment == true
2742*7304104dSAndroid Build Coastguard Worker                                   ? (char *)symstr_data->d_buf
2743*7304104dSAndroid Build Coastguard Worker                                         + vernaux->vna_name
2744*7304104dSAndroid Build Coastguard Worker                                   : elf_strptr (ebl->elf, verneed_stridx,
2745*7304104dSAndroid Build Coastguard Worker                                                 vernaux->vna_name),
2746*7304104dSAndroid Build Coastguard Worker                               (unsigned int)vernaux->vna_other);
2747*7304104dSAndroid Build Coastguard Worker                       check_def = 0;
2748*7304104dSAndroid Build Coastguard Worker                     }
2749*7304104dSAndroid Build Coastguard Worker                   else if (unlikely (!is_nobits))
2750*7304104dSAndroid Build Coastguard Worker                     error (0, 0, _ ("bad dynamic symbol"));
2751*7304104dSAndroid Build Coastguard Worker                   else
2752*7304104dSAndroid Build Coastguard Worker                     check_def = 1;
2753*7304104dSAndroid Build Coastguard Worker                 }
2754*7304104dSAndroid Build Coastguard Worker 
2755*7304104dSAndroid Build Coastguard Worker               if (check_def && *versym != 0x8001)
2756*7304104dSAndroid Build Coastguard Worker                 {
2757*7304104dSAndroid Build Coastguard Worker                   /* We must test both.  */
2758*7304104dSAndroid Build Coastguard Worker                   size_t vd_offset = 0;
2759*7304104dSAndroid Build Coastguard Worker 
2760*7304104dSAndroid Build Coastguard Worker                   GElf_Verdef verdef_mem;
2761*7304104dSAndroid Build Coastguard Worker                   GElf_Verdef *verdef
2762*7304104dSAndroid Build Coastguard Worker                       = gelf_getverdef (verdef_data, 0, &verdef_mem);
2763*7304104dSAndroid Build Coastguard Worker                   while (verdef != NULL)
2764*7304104dSAndroid Build Coastguard Worker                     {
2765*7304104dSAndroid Build Coastguard Worker                       if (verdef->vd_ndx == (*versym & 0x7fff))
2766*7304104dSAndroid Build Coastguard Worker                         /* Found the definition.  */
2767*7304104dSAndroid Build Coastguard Worker                         break;
2768*7304104dSAndroid Build Coastguard Worker 
2769*7304104dSAndroid Build Coastguard Worker                       if (verdef_data->d_size - vd_offset < verdef->vd_next)
2770*7304104dSAndroid Build Coastguard Worker                         break;
2771*7304104dSAndroid Build Coastguard Worker 
2772*7304104dSAndroid Build Coastguard Worker                       vd_offset += verdef->vd_next;
2773*7304104dSAndroid Build Coastguard Worker                       verdef = (verdef->vd_next == 0
2774*7304104dSAndroid Build Coastguard Worker                                     ? NULL
2775*7304104dSAndroid Build Coastguard Worker                                     : gelf_getverdef (verdef_data, vd_offset,
2776*7304104dSAndroid Build Coastguard Worker                                                       &verdef_mem));
2777*7304104dSAndroid Build Coastguard Worker                     }
2778*7304104dSAndroid Build Coastguard Worker 
2779*7304104dSAndroid Build Coastguard Worker                   if (verdef != NULL)
2780*7304104dSAndroid Build Coastguard Worker                     {
2781*7304104dSAndroid Build Coastguard Worker                       GElf_Verdaux verdaux_mem;
2782*7304104dSAndroid Build Coastguard Worker                       GElf_Verdaux *verdaux = gelf_getverdaux (
2783*7304104dSAndroid Build Coastguard Worker                           verdef_data, vd_offset + verdef->vd_aux,
2784*7304104dSAndroid Build Coastguard Worker                           &verdaux_mem);
2785*7304104dSAndroid Build Coastguard Worker 
2786*7304104dSAndroid Build Coastguard Worker                       if (verdaux != NULL)
2787*7304104dSAndroid Build Coastguard Worker                         printf ((*versym & 0x8000) ? "@%s" : "@@%s",
2788*7304104dSAndroid Build Coastguard Worker                                 use_dynamic_segment == true
2789*7304104dSAndroid Build Coastguard Worker                                     ? (char *)symstr_data->d_buf
2790*7304104dSAndroid Build Coastguard Worker                                           + verdaux->vda_name
2791*7304104dSAndroid Build Coastguard Worker                                     : elf_strptr (ebl->elf, verdef_stridx,
2792*7304104dSAndroid Build Coastguard Worker                                                   verdaux->vda_name));
2793*7304104dSAndroid Build Coastguard Worker                     }
2794*7304104dSAndroid Build Coastguard Worker                 }
2795*7304104dSAndroid Build Coastguard Worker             }
2796*7304104dSAndroid Build Coastguard Worker         }
2797*7304104dSAndroid Build Coastguard Worker 
2798*7304104dSAndroid Build Coastguard Worker       putchar_unlocked ('\n');
2799*7304104dSAndroid Build Coastguard Worker     }
2800*7304104dSAndroid Build Coastguard Worker }
2801*7304104dSAndroid Build Coastguard Worker 
2802*7304104dSAndroid Build Coastguard Worker 
2803*7304104dSAndroid Build Coastguard Worker static bool
handle_symtab(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr)2804*7304104dSAndroid Build Coastguard Worker handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
2805*7304104dSAndroid Build Coastguard Worker {
2806*7304104dSAndroid Build Coastguard Worker   Elf_Data *versym_data = NULL;
2807*7304104dSAndroid Build Coastguard Worker   Elf_Data *verneed_data = NULL;
2808*7304104dSAndroid Build Coastguard Worker   Elf_Data *verdef_data = NULL;
2809*7304104dSAndroid Build Coastguard Worker   Elf_Data *xndx_data = NULL;
2810*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
2811*7304104dSAndroid Build Coastguard Worker   Elf32_Word verneed_stridx = 0;
2812*7304104dSAndroid Build Coastguard Worker   Elf32_Word verdef_stridx = 0;
2813*7304104dSAndroid Build Coastguard Worker 
2814*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
2815*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
2816*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
2817*7304104dSAndroid Build Coastguard Worker     return false;
2818*7304104dSAndroid Build Coastguard Worker 
2819*7304104dSAndroid Build Coastguard Worker   /* Find out whether we have other sections we might need.  */
2820*7304104dSAndroid Build Coastguard Worker   Elf_Scn *runscn = NULL;
2821*7304104dSAndroid Build Coastguard Worker   while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
2822*7304104dSAndroid Build Coastguard Worker     {
2823*7304104dSAndroid Build Coastguard Worker       GElf_Shdr runshdr_mem;
2824*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
2825*7304104dSAndroid Build Coastguard Worker 
2826*7304104dSAndroid Build Coastguard Worker       if (likely (runshdr != NULL))
2827*7304104dSAndroid Build Coastguard Worker 	{
2828*7304104dSAndroid Build Coastguard Worker 	  if (runshdr->sh_type == SHT_GNU_versym
2829*7304104dSAndroid Build Coastguard Worker 	      && runshdr->sh_link == elf_ndxscn (scn))
2830*7304104dSAndroid Build Coastguard Worker 	    /* Bingo, found the version information.  Now get the data.  */
2831*7304104dSAndroid Build Coastguard Worker 	    versym_data = elf_getdata (runscn, NULL);
2832*7304104dSAndroid Build Coastguard Worker 	  else if (runshdr->sh_type == SHT_GNU_verneed)
2833*7304104dSAndroid Build Coastguard Worker 	    {
2834*7304104dSAndroid Build Coastguard Worker 	      /* This is the information about the needed versions.  */
2835*7304104dSAndroid Build Coastguard Worker 	      verneed_data = elf_getdata (runscn, NULL);
2836*7304104dSAndroid Build Coastguard Worker 	      verneed_stridx = runshdr->sh_link;
2837*7304104dSAndroid Build Coastguard Worker 	    }
2838*7304104dSAndroid Build Coastguard Worker 	  else if (runshdr->sh_type == SHT_GNU_verdef)
2839*7304104dSAndroid Build Coastguard Worker 	    {
2840*7304104dSAndroid Build Coastguard Worker 	      /* This is the information about the defined versions.  */
2841*7304104dSAndroid Build Coastguard Worker 	      verdef_data = elf_getdata (runscn, NULL);
2842*7304104dSAndroid Build Coastguard Worker 	      verdef_stridx = runshdr->sh_link;
2843*7304104dSAndroid Build Coastguard Worker 	    }
2844*7304104dSAndroid Build Coastguard Worker 	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
2845*7304104dSAndroid Build Coastguard Worker 	      && runshdr->sh_link == elf_ndxscn (scn))
2846*7304104dSAndroid Build Coastguard Worker 	    /* Extended section index.  */
2847*7304104dSAndroid Build Coastguard Worker 	    xndx_data = elf_getdata (runscn, NULL);
2848*7304104dSAndroid Build Coastguard Worker 	}
2849*7304104dSAndroid Build Coastguard Worker     }
2850*7304104dSAndroid Build Coastguard Worker 
2851*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
2852*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
2853*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
2854*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
2855*7304104dSAndroid Build Coastguard Worker 
2856*7304104dSAndroid Build Coastguard Worker   GElf_Shdr glink_mem;
2857*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
2858*7304104dSAndroid Build Coastguard Worker 				   &glink_mem);
2859*7304104dSAndroid Build Coastguard Worker   if (glink == NULL)
2860*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("invalid sh_link value in section %zu"),
2861*7304104dSAndroid Build Coastguard Worker 		elf_ndxscn (scn));
2862*7304104dSAndroid Build Coastguard Worker 
2863*7304104dSAndroid Build Coastguard Worker   /* Now we can compute the number of entries in the section.  */
2864*7304104dSAndroid Build Coastguard Worker   unsigned int nsyms = data->d_size / (class == ELFCLASS32
2865*7304104dSAndroid Build Coastguard Worker 				       ? sizeof (Elf32_Sym)
2866*7304104dSAndroid Build Coastguard Worker 				       : sizeof (Elf64_Sym));
2867*7304104dSAndroid Build Coastguard Worker 
2868*7304104dSAndroid Build Coastguard Worker   printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
2869*7304104dSAndroid Build Coastguard Worker 		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
2870*7304104dSAndroid Build Coastguard Worker 		    nsyms),
2871*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) elf_ndxscn (scn),
2872*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
2873*7304104dSAndroid Build Coastguard Worker   printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
2874*7304104dSAndroid Build Coastguard Worker 		    " %lu local symbols  String table: [%2u] '%s'\n",
2875*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_info),
2876*7304104dSAndroid Build Coastguard Worker 	  (unsigned long int) shdr->sh_info,
2877*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) shdr->sh_link,
2878*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
2879*7304104dSAndroid Build Coastguard Worker 
2880*7304104dSAndroid Build Coastguard Worker   fputs_unlocked (class == ELFCLASS32
2881*7304104dSAndroid Build Coastguard Worker 		  ? _("\
2882*7304104dSAndroid Build Coastguard Worker   Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
2883*7304104dSAndroid Build Coastguard Worker 		  : _("\
2884*7304104dSAndroid Build Coastguard Worker   Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
2885*7304104dSAndroid Build Coastguard Worker 		  stdout);
2886*7304104dSAndroid Build Coastguard Worker 
2887*7304104dSAndroid Build Coastguard Worker 	process_symtab(ebl, nsyms, shdr->sh_link, verneed_stridx, verdef_stridx,
2888*7304104dSAndroid Build Coastguard Worker 	data, versym_data, NULL, verneed_data, verdef_data, xndx_data);
2889*7304104dSAndroid Build Coastguard Worker     return true;
2890*7304104dSAndroid Build Coastguard Worker }
2891*7304104dSAndroid Build Coastguard Worker 
2892*7304104dSAndroid Build Coastguard Worker 
2893*7304104dSAndroid Build Coastguard Worker static bool
handle_dynamic_symtab(Ebl * ebl)2894*7304104dSAndroid Build Coastguard Worker handle_dynamic_symtab (Ebl *ebl)
2895*7304104dSAndroid Build Coastguard Worker {
2896*7304104dSAndroid Build Coastguard Worker   GElf_Phdr phdr_mem;
2897*7304104dSAndroid Build Coastguard Worker   GElf_Phdr *phdr = NULL;
2898*7304104dSAndroid Build Coastguard Worker   /* phnum is a static variable which was already fetched in function
2899*7304104dSAndroid Build Coastguard Worker      process_elf_file.  */
2900*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < phnum; ++i)
2901*7304104dSAndroid Build Coastguard Worker     {
2902*7304104dSAndroid Build Coastguard Worker       phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
2903*7304104dSAndroid Build Coastguard Worker       if (phdr->p_type == PT_DYNAMIC)
2904*7304104dSAndroid Build Coastguard Worker 	break;
2905*7304104dSAndroid Build Coastguard Worker     }
2906*7304104dSAndroid Build Coastguard Worker   if (phdr == NULL)
2907*7304104dSAndroid Build Coastguard Worker     return false;
2908*7304104dSAndroid Build Coastguard Worker 
2909*7304104dSAndroid Build Coastguard Worker   GElf_Addr addrs[i_max] = {
2910*7304104dSAndroid Build Coastguard Worker     0,
2911*7304104dSAndroid Build Coastguard Worker   };
2912*7304104dSAndroid Build Coastguard Worker   GElf_Off offs[i_max] = {
2913*7304104dSAndroid Build Coastguard Worker     0,
2914*7304104dSAndroid Build Coastguard Worker   };
2915*7304104dSAndroid Build Coastguard Worker   get_dynscn_addrs (ebl->elf, phdr, addrs);
2916*7304104dSAndroid Build Coastguard Worker   find_offsets (ebl->elf, 0, i_max, addrs, offs);
2917*7304104dSAndroid Build Coastguard Worker 
2918*7304104dSAndroid Build Coastguard Worker   size_t syments = 0;
2919*7304104dSAndroid Build Coastguard Worker 
2920*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr ehdr_mem;
2921*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr *ehdr = gelf_getehdr (ebl->elf, &ehdr_mem);
2922*7304104dSAndroid Build Coastguard Worker 
2923*7304104dSAndroid Build Coastguard Worker   if (offs[i_hash] != 0)
2924*7304104dSAndroid Build Coastguard Worker     {
2925*7304104dSAndroid Build Coastguard Worker       /* In the original format, .hash says the size of .dynsym.  */
2926*7304104dSAndroid Build Coastguard Worker 
2927*7304104dSAndroid Build Coastguard Worker       size_t entsz = SH_ENTSIZE_HASH (ehdr);
2928*7304104dSAndroid Build Coastguard Worker       Elf_Data *data
2929*7304104dSAndroid Build Coastguard Worker           = elf_getdata_rawchunk (ebl->elf, offs[i_hash] + entsz, entsz,
2930*7304104dSAndroid Build Coastguard Worker                                   (entsz == 4 ? ELF_T_WORD : ELF_T_XWORD));
2931*7304104dSAndroid Build Coastguard Worker       if (data != NULL)
2932*7304104dSAndroid Build Coastguard Worker         syments = (entsz == 4 ? *(const GElf_Word *)data->d_buf
2933*7304104dSAndroid Build Coastguard Worker                               : *(const GElf_Xword *)data->d_buf);
2934*7304104dSAndroid Build Coastguard Worker     }
2935*7304104dSAndroid Build Coastguard Worker   if (offs[i_gnu_hash] != 0 && syments == 0)
2936*7304104dSAndroid Build Coastguard Worker     {
2937*7304104dSAndroid Build Coastguard Worker       /* In the new format, we can derive it with some work.  */
2938*7304104dSAndroid Build Coastguard Worker 
2939*7304104dSAndroid Build Coastguard Worker       const struct
2940*7304104dSAndroid Build Coastguard Worker       {
2941*7304104dSAndroid Build Coastguard Worker         Elf32_Word nbuckets;
2942*7304104dSAndroid Build Coastguard Worker         Elf32_Word symndx;
2943*7304104dSAndroid Build Coastguard Worker         Elf32_Word maskwords;
2944*7304104dSAndroid Build Coastguard Worker         Elf32_Word shift2;
2945*7304104dSAndroid Build Coastguard Worker       } * header;
2946*7304104dSAndroid Build Coastguard Worker 
2947*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_getdata_rawchunk (ebl->elf, offs[i_gnu_hash],
2948*7304104dSAndroid Build Coastguard Worker                                              sizeof *header, ELF_T_WORD);
2949*7304104dSAndroid Build Coastguard Worker       if (data != NULL)
2950*7304104dSAndroid Build Coastguard Worker         {
2951*7304104dSAndroid Build Coastguard Worker           header = data->d_buf;
2952*7304104dSAndroid Build Coastguard Worker           Elf32_Word nbuckets = header->nbuckets;
2953*7304104dSAndroid Build Coastguard Worker           Elf32_Word symndx = header->symndx;
2954*7304104dSAndroid Build Coastguard Worker           GElf_Off buckets_at
2955*7304104dSAndroid Build Coastguard Worker               = (offs[i_gnu_hash] + sizeof *header
2956*7304104dSAndroid Build Coastguard Worker                  + (gelf_getclass (ebl->elf) * sizeof (Elf32_Word)
2957*7304104dSAndroid Build Coastguard Worker                     * header->maskwords));
2958*7304104dSAndroid Build Coastguard Worker 
2959*7304104dSAndroid Build Coastguard Worker           // elf_getdata_rawchunk takes a size_t, make sure it
2960*7304104dSAndroid Build Coastguard Worker           // doesn't overflow.
2961*7304104dSAndroid Build Coastguard Worker #if SIZE_MAX <= UINT32_MAX
2962*7304104dSAndroid Build Coastguard Worker           if (nbuckets > SIZE_MAX / sizeof (Elf32_Word))
2963*7304104dSAndroid Build Coastguard Worker             data = NULL;
2964*7304104dSAndroid Build Coastguard Worker           else
2965*7304104dSAndroid Build Coastguard Worker #endif
2966*7304104dSAndroid Build Coastguard Worker             data = elf_getdata_rawchunk (ebl->elf, buckets_at,
2967*7304104dSAndroid Build Coastguard Worker                                          nbuckets * sizeof (Elf32_Word),
2968*7304104dSAndroid Build Coastguard Worker                                          ELF_T_WORD);
2969*7304104dSAndroid Build Coastguard Worker           if (data != NULL && symndx < nbuckets)
2970*7304104dSAndroid Build Coastguard Worker             {
2971*7304104dSAndroid Build Coastguard Worker               const Elf32_Word *const buckets = data->d_buf;
2972*7304104dSAndroid Build Coastguard Worker               Elf32_Word maxndx = symndx;
2973*7304104dSAndroid Build Coastguard Worker               for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
2974*7304104dSAndroid Build Coastguard Worker                 if (buckets[bucket] > maxndx)
2975*7304104dSAndroid Build Coastguard Worker                   maxndx = buckets[bucket];
2976*7304104dSAndroid Build Coastguard Worker 
2977*7304104dSAndroid Build Coastguard Worker               GElf_Off hasharr_at
2978*7304104dSAndroid Build Coastguard Worker                   = (buckets_at + nbuckets * sizeof (Elf32_Word));
2979*7304104dSAndroid Build Coastguard Worker               hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
2980*7304104dSAndroid Build Coastguard Worker               do
2981*7304104dSAndroid Build Coastguard Worker                 {
2982*7304104dSAndroid Build Coastguard Worker                   data = elf_getdata_rawchunk (
2983*7304104dSAndroid Build Coastguard Worker                       ebl->elf, hasharr_at, sizeof (Elf32_Word), ELF_T_WORD);
2984*7304104dSAndroid Build Coastguard Worker                   if (data != NULL && (*(const Elf32_Word *)data->d_buf & 1u))
2985*7304104dSAndroid Build Coastguard Worker                     {
2986*7304104dSAndroid Build Coastguard Worker                       syments = maxndx + 1;
2987*7304104dSAndroid Build Coastguard Worker                       break;
2988*7304104dSAndroid Build Coastguard Worker                     }
2989*7304104dSAndroid Build Coastguard Worker                   ++maxndx;
2990*7304104dSAndroid Build Coastguard Worker                   hasharr_at += sizeof (Elf32_Word);
2991*7304104dSAndroid Build Coastguard Worker                 }
2992*7304104dSAndroid Build Coastguard Worker               while (data != NULL);
2993*7304104dSAndroid Build Coastguard Worker             }
2994*7304104dSAndroid Build Coastguard Worker         }
2995*7304104dSAndroid Build Coastguard Worker     }
2996*7304104dSAndroid Build Coastguard Worker   if (offs[i_strtab] > offs[i_symtab] && syments == 0)
2997*7304104dSAndroid Build Coastguard Worker     syments = ((offs[i_strtab] - offs[i_symtab])
2998*7304104dSAndroid Build Coastguard Worker                / gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT));
2999*7304104dSAndroid Build Coastguard Worker 
3000*7304104dSAndroid Build Coastguard Worker   if (syments <= 0 || offs[i_strtab] == 0 || offs[i_symtab] == 0)
3001*7304104dSAndroid Build Coastguard Worker     {
3002*7304104dSAndroid Build Coastguard Worker       error_exit (0, _ ("Dynamic symbol information is not available for "
3003*7304104dSAndroid Build Coastguard Worker                         "displaying symbols."));
3004*7304104dSAndroid Build Coastguard Worker     }
3005*7304104dSAndroid Build Coastguard Worker 
3006*7304104dSAndroid Build Coastguard Worker   /* All the data chunk initializaion.  */
3007*7304104dSAndroid Build Coastguard Worker   Elf_Data *symdata = NULL;
3008*7304104dSAndroid Build Coastguard Worker   Elf_Data *symstrdata = NULL;
3009*7304104dSAndroid Build Coastguard Worker   Elf_Data *versym_data = NULL;
3010*7304104dSAndroid Build Coastguard Worker   Elf_Data *verdef_data = NULL;
3011*7304104dSAndroid Build Coastguard Worker   Elf_Data *verneed_data = NULL;
3012*7304104dSAndroid Build Coastguard Worker 
3013*7304104dSAndroid Build Coastguard Worker   symdata = elf_getdata_rawchunk (
3014*7304104dSAndroid Build Coastguard Worker       ebl->elf, offs[i_symtab],
3015*7304104dSAndroid Build Coastguard Worker       gelf_fsize (ebl->elf, ELF_T_SYM, syments, EV_CURRENT), ELF_T_SYM);
3016*7304104dSAndroid Build Coastguard Worker   symstrdata = elf_getdata_rawchunk (ebl->elf, offs[i_strtab], addrs[i_strsz],
3017*7304104dSAndroid Build Coastguard Worker                                      ELF_T_BYTE);
3018*7304104dSAndroid Build Coastguard Worker   versym_data = elf_getdata_rawchunk (
3019*7304104dSAndroid Build Coastguard Worker       ebl->elf, offs[i_versym], syments * sizeof (Elf64_Half), ELF_T_HALF);
3020*7304104dSAndroid Build Coastguard Worker 
3021*7304104dSAndroid Build Coastguard Worker   /* Get the verneed_data without vernaux.  */
3022*7304104dSAndroid Build Coastguard Worker   verneed_data = elf_getdata_rawchunk (
3023*7304104dSAndroid Build Coastguard Worker       ebl->elf, offs[i_verneed], addrs[i_verneednum] * sizeof (Elf64_Verneed),
3024*7304104dSAndroid Build Coastguard Worker       ELF_T_VNEED);
3025*7304104dSAndroid Build Coastguard Worker   size_t vernauxnum = 0;
3026*7304104dSAndroid Build Coastguard Worker   size_t vn_next_offset = 0;
3027*7304104dSAndroid Build Coastguard Worker 
3028*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < addrs[i_verneednum]; i++)
3029*7304104dSAndroid Build Coastguard Worker     {
3030*7304104dSAndroid Build Coastguard Worker       GElf_Verneed *verneed
3031*7304104dSAndroid Build Coastguard Worker           = (GElf_Verneed *)(verneed_data->d_buf + vn_next_offset);
3032*7304104dSAndroid Build Coastguard Worker       vernauxnum += verneed->vn_cnt;
3033*7304104dSAndroid Build Coastguard Worker       vn_next_offset += verneed->vn_next;
3034*7304104dSAndroid Build Coastguard Worker     }
3035*7304104dSAndroid Build Coastguard Worker 
3036*7304104dSAndroid Build Coastguard Worker   /* Update the verneed_data to include the vernaux.  */
3037*7304104dSAndroid Build Coastguard Worker   verneed_data = elf_getdata_rawchunk (
3038*7304104dSAndroid Build Coastguard Worker       ebl->elf, offs[i_verneed],
3039*7304104dSAndroid Build Coastguard Worker       (addrs[i_verneednum] + vernauxnum) * sizeof (GElf_Verneed), ELF_T_VNEED);
3040*7304104dSAndroid Build Coastguard Worker 
3041*7304104dSAndroid Build Coastguard Worker   /* Get the verdef_data without verdaux.  */
3042*7304104dSAndroid Build Coastguard Worker   verdef_data = elf_getdata_rawchunk (
3043*7304104dSAndroid Build Coastguard Worker       ebl->elf, offs[i_verdef], addrs[i_verdefnum] * sizeof (Elf64_Verdef),
3044*7304104dSAndroid Build Coastguard Worker       ELF_T_VDEF);
3045*7304104dSAndroid Build Coastguard Worker   size_t verdauxnum = 0;
3046*7304104dSAndroid Build Coastguard Worker   size_t vd_next_offset = 0;
3047*7304104dSAndroid Build Coastguard Worker 
3048*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < addrs[i_verdefnum]; i++)
3049*7304104dSAndroid Build Coastguard Worker     {
3050*7304104dSAndroid Build Coastguard Worker       GElf_Verdef *verdef
3051*7304104dSAndroid Build Coastguard Worker           = (GElf_Verdef *)(verdef_data->d_buf + vd_next_offset);
3052*7304104dSAndroid Build Coastguard Worker       verdauxnum += verdef->vd_cnt;
3053*7304104dSAndroid Build Coastguard Worker       vd_next_offset += verdef->vd_next;
3054*7304104dSAndroid Build Coastguard Worker     }
3055*7304104dSAndroid Build Coastguard Worker 
3056*7304104dSAndroid Build Coastguard Worker   /* Update the verdef_data to include the verdaux.  */
3057*7304104dSAndroid Build Coastguard Worker   verdef_data = elf_getdata_rawchunk (
3058*7304104dSAndroid Build Coastguard Worker       ebl->elf, offs[i_verdef],
3059*7304104dSAndroid Build Coastguard Worker       (addrs[i_verdefnum] + verdauxnum) * sizeof (GElf_Verdef), ELF_T_VDEF);
3060*7304104dSAndroid Build Coastguard Worker 
3061*7304104dSAndroid Build Coastguard Worker   unsigned int nsyms = (unsigned int)syments;
3062*7304104dSAndroid Build Coastguard Worker   process_symtab (ebl, nsyms, 0, 0, 0, symdata, versym_data, symstrdata,
3063*7304104dSAndroid Build Coastguard Worker                   verneed_data, verdef_data, NULL);
3064*7304104dSAndroid Build Coastguard Worker   return true;
3065*7304104dSAndroid Build Coastguard Worker }
3066*7304104dSAndroid Build Coastguard Worker 
3067*7304104dSAndroid Build Coastguard Worker 
3068*7304104dSAndroid Build Coastguard Worker /* Print version information.  */
3069*7304104dSAndroid Build Coastguard Worker static void
print_verinfo(Ebl * ebl)3070*7304104dSAndroid Build Coastguard Worker print_verinfo (Ebl *ebl)
3071*7304104dSAndroid Build Coastguard Worker {
3072*7304104dSAndroid Build Coastguard Worker   /* Find the version information sections.  For this we have to
3073*7304104dSAndroid Build Coastguard Worker      search through the section table.  */
3074*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
3075*7304104dSAndroid Build Coastguard Worker 
3076*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3077*7304104dSAndroid Build Coastguard Worker     {
3078*7304104dSAndroid Build Coastguard Worker       /* Handle the section if it is part of the versioning handling.  */
3079*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
3080*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3081*7304104dSAndroid Build Coastguard Worker 
3082*7304104dSAndroid Build Coastguard Worker       if (likely (shdr != NULL))
3083*7304104dSAndroid Build Coastguard Worker 	{
3084*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_type == SHT_GNU_verneed)
3085*7304104dSAndroid Build Coastguard Worker 	    handle_verneed (ebl, scn, shdr);
3086*7304104dSAndroid Build Coastguard Worker 	  else if (shdr->sh_type == SHT_GNU_verdef)
3087*7304104dSAndroid Build Coastguard Worker 	    handle_verdef (ebl, scn, shdr);
3088*7304104dSAndroid Build Coastguard Worker 	  else if (shdr->sh_type == SHT_GNU_versym)
3089*7304104dSAndroid Build Coastguard Worker 	    handle_versym (ebl, scn, shdr);
3090*7304104dSAndroid Build Coastguard Worker 	}
3091*7304104dSAndroid Build Coastguard Worker     }
3092*7304104dSAndroid Build Coastguard Worker }
3093*7304104dSAndroid Build Coastguard Worker 
3094*7304104dSAndroid Build Coastguard Worker 
3095*7304104dSAndroid Build Coastguard Worker static const char *
get_ver_flags(unsigned int flags)3096*7304104dSAndroid Build Coastguard Worker get_ver_flags (unsigned int flags)
3097*7304104dSAndroid Build Coastguard Worker {
3098*7304104dSAndroid Build Coastguard Worker   static char buf[32];
3099*7304104dSAndroid Build Coastguard Worker   char *endp;
3100*7304104dSAndroid Build Coastguard Worker 
3101*7304104dSAndroid Build Coastguard Worker   if (flags == 0)
3102*7304104dSAndroid Build Coastguard Worker     return _("none");
3103*7304104dSAndroid Build Coastguard Worker 
3104*7304104dSAndroid Build Coastguard Worker   if (flags & VER_FLG_BASE)
3105*7304104dSAndroid Build Coastguard Worker     endp = stpcpy (buf, "BASE ");
3106*7304104dSAndroid Build Coastguard Worker   else
3107*7304104dSAndroid Build Coastguard Worker     endp = buf;
3108*7304104dSAndroid Build Coastguard Worker 
3109*7304104dSAndroid Build Coastguard Worker   if (flags & VER_FLG_WEAK)
3110*7304104dSAndroid Build Coastguard Worker     {
3111*7304104dSAndroid Build Coastguard Worker       if (endp != buf)
3112*7304104dSAndroid Build Coastguard Worker 	endp = stpcpy (endp, "| ");
3113*7304104dSAndroid Build Coastguard Worker 
3114*7304104dSAndroid Build Coastguard Worker       endp = stpcpy (endp, "WEAK ");
3115*7304104dSAndroid Build Coastguard Worker     }
3116*7304104dSAndroid Build Coastguard Worker 
3117*7304104dSAndroid Build Coastguard Worker   if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
3118*7304104dSAndroid Build Coastguard Worker     {
3119*7304104dSAndroid Build Coastguard Worker       strncpy (endp, _("| <unknown>"), buf + sizeof (buf) - endp);
3120*7304104dSAndroid Build Coastguard Worker       buf[sizeof (buf) - 1] = '\0';
3121*7304104dSAndroid Build Coastguard Worker     }
3122*7304104dSAndroid Build Coastguard Worker 
3123*7304104dSAndroid Build Coastguard Worker   return buf;
3124*7304104dSAndroid Build Coastguard Worker }
3125*7304104dSAndroid Build Coastguard Worker 
3126*7304104dSAndroid Build Coastguard Worker 
3127*7304104dSAndroid Build Coastguard Worker static void
handle_verneed(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr)3128*7304104dSAndroid Build Coastguard Worker handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
3129*7304104dSAndroid Build Coastguard Worker {
3130*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
3131*7304104dSAndroid Build Coastguard Worker 
3132*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
3133*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
3134*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
3135*7304104dSAndroid Build Coastguard Worker     return;
3136*7304104dSAndroid Build Coastguard Worker 
3137*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
3138*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
3139*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3140*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
3141*7304104dSAndroid Build Coastguard Worker 
3142*7304104dSAndroid Build Coastguard Worker   GElf_Shdr glink_mem;
3143*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3144*7304104dSAndroid Build Coastguard Worker 				   &glink_mem);
3145*7304104dSAndroid Build Coastguard Worker   if (glink == NULL)
3146*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("invalid sh_link value in section %zu"),
3147*7304104dSAndroid Build Coastguard Worker 		elf_ndxscn (scn));
3148*7304104dSAndroid Build Coastguard Worker 
3149*7304104dSAndroid Build Coastguard Worker   printf (ngettext ("\
3150*7304104dSAndroid Build Coastguard Worker \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
3151*7304104dSAndroid Build Coastguard Worker 		    "\
3152*7304104dSAndroid Build Coastguard Worker \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
3153*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_info),
3154*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) elf_ndxscn (scn),
3155*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
3156*7304104dSAndroid Build Coastguard Worker 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
3157*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_offset,
3158*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) shdr->sh_link,
3159*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3160*7304104dSAndroid Build Coastguard Worker 
3161*7304104dSAndroid Build Coastguard Worker   unsigned int offset = 0;
3162*7304104dSAndroid Build Coastguard Worker   for (unsigned int cnt = shdr->sh_info; cnt > 0; cnt--)
3163*7304104dSAndroid Build Coastguard Worker     {
3164*7304104dSAndroid Build Coastguard Worker       /* Get the data at the next offset.  */
3165*7304104dSAndroid Build Coastguard Worker       GElf_Verneed needmem;
3166*7304104dSAndroid Build Coastguard Worker       GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
3167*7304104dSAndroid Build Coastguard Worker       if (unlikely (need == NULL))
3168*7304104dSAndroid Build Coastguard Worker 	break;
3169*7304104dSAndroid Build Coastguard Worker 
3170*7304104dSAndroid Build Coastguard Worker       printf (_("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
3171*7304104dSAndroid Build Coastguard Worker 	      offset, (unsigned short int) need->vn_version,
3172*7304104dSAndroid Build Coastguard Worker 	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
3173*7304104dSAndroid Build Coastguard Worker 	      (unsigned short int) need->vn_cnt);
3174*7304104dSAndroid Build Coastguard Worker 
3175*7304104dSAndroid Build Coastguard Worker       unsigned int auxoffset = offset + need->vn_aux;
3176*7304104dSAndroid Build Coastguard Worker       for (unsigned int cnt2 = need->vn_cnt; cnt2 > 0; cnt2--)
3177*7304104dSAndroid Build Coastguard Worker 	{
3178*7304104dSAndroid Build Coastguard Worker 	  GElf_Vernaux auxmem;
3179*7304104dSAndroid Build Coastguard Worker 	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
3180*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (aux == NULL))
3181*7304104dSAndroid Build Coastguard Worker 	    break;
3182*7304104dSAndroid Build Coastguard Worker 
3183*7304104dSAndroid Build Coastguard Worker 	  printf (_("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
3184*7304104dSAndroid Build Coastguard Worker 		  auxoffset,
3185*7304104dSAndroid Build Coastguard Worker 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
3186*7304104dSAndroid Build Coastguard Worker 		  get_ver_flags (aux->vna_flags),
3187*7304104dSAndroid Build Coastguard Worker 		  (unsigned short int) aux->vna_other);
3188*7304104dSAndroid Build Coastguard Worker 
3189*7304104dSAndroid Build Coastguard Worker 	  if (aux->vna_next == 0)
3190*7304104dSAndroid Build Coastguard Worker 	    break;
3191*7304104dSAndroid Build Coastguard Worker 
3192*7304104dSAndroid Build Coastguard Worker 	  auxoffset += aux->vna_next;
3193*7304104dSAndroid Build Coastguard Worker 	}
3194*7304104dSAndroid Build Coastguard Worker 
3195*7304104dSAndroid Build Coastguard Worker       /* Find the next offset.  */
3196*7304104dSAndroid Build Coastguard Worker       if (need->vn_next == 0)
3197*7304104dSAndroid Build Coastguard Worker 	break;
3198*7304104dSAndroid Build Coastguard Worker 
3199*7304104dSAndroid Build Coastguard Worker       offset += need->vn_next;
3200*7304104dSAndroid Build Coastguard Worker     }
3201*7304104dSAndroid Build Coastguard Worker }
3202*7304104dSAndroid Build Coastguard Worker 
3203*7304104dSAndroid Build Coastguard Worker 
3204*7304104dSAndroid Build Coastguard Worker static void
handle_verdef(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr)3205*7304104dSAndroid Build Coastguard Worker handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
3206*7304104dSAndroid Build Coastguard Worker {
3207*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
3208*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
3209*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
3210*7304104dSAndroid Build Coastguard Worker     return;
3211*7304104dSAndroid Build Coastguard Worker 
3212*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
3213*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
3214*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3215*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
3216*7304104dSAndroid Build Coastguard Worker 
3217*7304104dSAndroid Build Coastguard Worker   GElf_Shdr glink_mem;
3218*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3219*7304104dSAndroid Build Coastguard Worker 				   &glink_mem);
3220*7304104dSAndroid Build Coastguard Worker   if (glink == NULL)
3221*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("invalid sh_link value in section %zu"),
3222*7304104dSAndroid Build Coastguard Worker 		elf_ndxscn (scn));
3223*7304104dSAndroid Build Coastguard Worker 
3224*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
3225*7304104dSAndroid Build Coastguard Worker   printf (ngettext ("\
3226*7304104dSAndroid Build Coastguard Worker \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
3227*7304104dSAndroid Build Coastguard Worker 		    "\
3228*7304104dSAndroid Build Coastguard Worker \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
3229*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_info),
3230*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) elf_ndxscn (scn),
3231*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3232*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_info,
3233*7304104dSAndroid Build Coastguard Worker 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
3234*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_offset,
3235*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) shdr->sh_link,
3236*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3237*7304104dSAndroid Build Coastguard Worker 
3238*7304104dSAndroid Build Coastguard Worker   unsigned int offset = 0;
3239*7304104dSAndroid Build Coastguard Worker   for (unsigned int cnt = shdr->sh_info; cnt > 0; cnt--)
3240*7304104dSAndroid Build Coastguard Worker     {
3241*7304104dSAndroid Build Coastguard Worker       /* Get the data at the next offset.  */
3242*7304104dSAndroid Build Coastguard Worker       GElf_Verdef defmem;
3243*7304104dSAndroid Build Coastguard Worker       GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
3244*7304104dSAndroid Build Coastguard Worker       if (unlikely (def == NULL))
3245*7304104dSAndroid Build Coastguard Worker 	break;
3246*7304104dSAndroid Build Coastguard Worker 
3247*7304104dSAndroid Build Coastguard Worker       unsigned int auxoffset = offset + def->vd_aux;
3248*7304104dSAndroid Build Coastguard Worker       GElf_Verdaux auxmem;
3249*7304104dSAndroid Build Coastguard Worker       GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
3250*7304104dSAndroid Build Coastguard Worker       if (unlikely (aux == NULL))
3251*7304104dSAndroid Build Coastguard Worker 	break;
3252*7304104dSAndroid Build Coastguard Worker 
3253*7304104dSAndroid Build Coastguard Worker       printf (_("\
3254*7304104dSAndroid Build Coastguard Worker   %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
3255*7304104dSAndroid Build Coastguard Worker 	      offset, def->vd_version,
3256*7304104dSAndroid Build Coastguard Worker 	      get_ver_flags (def->vd_flags),
3257*7304104dSAndroid Build Coastguard Worker 	      def->vd_ndx,
3258*7304104dSAndroid Build Coastguard Worker 	      def->vd_cnt,
3259*7304104dSAndroid Build Coastguard Worker 	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
3260*7304104dSAndroid Build Coastguard Worker 
3261*7304104dSAndroid Build Coastguard Worker       auxoffset += aux->vda_next;
3262*7304104dSAndroid Build Coastguard Worker       for (unsigned int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
3263*7304104dSAndroid Build Coastguard Worker 	{
3264*7304104dSAndroid Build Coastguard Worker 	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
3265*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (aux == NULL))
3266*7304104dSAndroid Build Coastguard Worker 	    break;
3267*7304104dSAndroid Build Coastguard Worker 
3268*7304104dSAndroid Build Coastguard Worker 	  printf (_("  %#06x: Parent %d: %s\n"),
3269*7304104dSAndroid Build Coastguard Worker 		  auxoffset, cnt2,
3270*7304104dSAndroid Build Coastguard Worker 		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
3271*7304104dSAndroid Build Coastguard Worker 
3272*7304104dSAndroid Build Coastguard Worker 	  if (aux->vda_next == 0)
3273*7304104dSAndroid Build Coastguard Worker 	    break;
3274*7304104dSAndroid Build Coastguard Worker 
3275*7304104dSAndroid Build Coastguard Worker 	  auxoffset += aux->vda_next;
3276*7304104dSAndroid Build Coastguard Worker 	}
3277*7304104dSAndroid Build Coastguard Worker 
3278*7304104dSAndroid Build Coastguard Worker       /* Find the next offset.  */
3279*7304104dSAndroid Build Coastguard Worker       if (def->vd_next == 0)
3280*7304104dSAndroid Build Coastguard Worker 	break;
3281*7304104dSAndroid Build Coastguard Worker       offset += def->vd_next;
3282*7304104dSAndroid Build Coastguard Worker     }
3283*7304104dSAndroid Build Coastguard Worker }
3284*7304104dSAndroid Build Coastguard Worker 
3285*7304104dSAndroid Build Coastguard Worker 
3286*7304104dSAndroid Build Coastguard Worker static void
handle_versym(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr)3287*7304104dSAndroid Build Coastguard Worker handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
3288*7304104dSAndroid Build Coastguard Worker {
3289*7304104dSAndroid Build Coastguard Worker   int class = gelf_getclass (ebl->elf);
3290*7304104dSAndroid Build Coastguard Worker   const char **vername;
3291*7304104dSAndroid Build Coastguard Worker   const char **filename;
3292*7304104dSAndroid Build Coastguard Worker 
3293*7304104dSAndroid Build Coastguard Worker   /* Get the data of the section.  */
3294*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
3295*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
3296*7304104dSAndroid Build Coastguard Worker     return;
3297*7304104dSAndroid Build Coastguard Worker 
3298*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
3299*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
3300*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3301*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
3302*7304104dSAndroid Build Coastguard Worker 
3303*7304104dSAndroid Build Coastguard Worker   /* We have to find the version definition section and extract the
3304*7304104dSAndroid Build Coastguard Worker      version names.  */
3305*7304104dSAndroid Build Coastguard Worker   Elf_Scn *defscn = NULL;
3306*7304104dSAndroid Build Coastguard Worker   Elf_Scn *needscn = NULL;
3307*7304104dSAndroid Build Coastguard Worker 
3308*7304104dSAndroid Build Coastguard Worker   Elf_Scn *verscn = NULL;
3309*7304104dSAndroid Build Coastguard Worker   while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
3310*7304104dSAndroid Build Coastguard Worker     {
3311*7304104dSAndroid Build Coastguard Worker       GElf_Shdr vershdr_mem;
3312*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
3313*7304104dSAndroid Build Coastguard Worker 
3314*7304104dSAndroid Build Coastguard Worker       if (likely (vershdr != NULL))
3315*7304104dSAndroid Build Coastguard Worker 	{
3316*7304104dSAndroid Build Coastguard Worker 	  if (vershdr->sh_type == SHT_GNU_verdef)
3317*7304104dSAndroid Build Coastguard Worker 	    defscn = verscn;
3318*7304104dSAndroid Build Coastguard Worker 	  else if (vershdr->sh_type == SHT_GNU_verneed)
3319*7304104dSAndroid Build Coastguard Worker 	    needscn = verscn;
3320*7304104dSAndroid Build Coastguard Worker 	}
3321*7304104dSAndroid Build Coastguard Worker     }
3322*7304104dSAndroid Build Coastguard Worker 
3323*7304104dSAndroid Build Coastguard Worker   size_t nvername;
3324*7304104dSAndroid Build Coastguard Worker   if (defscn != NULL || needscn != NULL)
3325*7304104dSAndroid Build Coastguard Worker     {
3326*7304104dSAndroid Build Coastguard Worker       /* We have a version information (better should have).  Now get
3327*7304104dSAndroid Build Coastguard Worker 	 the version names.  First find the maximum version number.  */
3328*7304104dSAndroid Build Coastguard Worker       nvername = 0;
3329*7304104dSAndroid Build Coastguard Worker       if (defscn != NULL)
3330*7304104dSAndroid Build Coastguard Worker 	{
3331*7304104dSAndroid Build Coastguard Worker 	  /* Run through the version definitions and find the highest
3332*7304104dSAndroid Build Coastguard Worker 	     index.  */
3333*7304104dSAndroid Build Coastguard Worker 	  unsigned int offset = 0;
3334*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *defdata;
3335*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr defshdrmem;
3336*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *defshdr;
3337*7304104dSAndroid Build Coastguard Worker 
3338*7304104dSAndroid Build Coastguard Worker 	  defdata = elf_getdata (defscn, NULL);
3339*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (defdata == NULL))
3340*7304104dSAndroid Build Coastguard Worker 	    return;
3341*7304104dSAndroid Build Coastguard Worker 
3342*7304104dSAndroid Build Coastguard Worker 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
3343*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (defshdr == NULL))
3344*7304104dSAndroid Build Coastguard Worker 	    return;
3345*7304104dSAndroid Build Coastguard Worker 
3346*7304104dSAndroid Build Coastguard Worker 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
3347*7304104dSAndroid Build Coastguard Worker 	    {
3348*7304104dSAndroid Build Coastguard Worker 	      GElf_Verdef defmem;
3349*7304104dSAndroid Build Coastguard Worker 	      GElf_Verdef *def;
3350*7304104dSAndroid Build Coastguard Worker 
3351*7304104dSAndroid Build Coastguard Worker 	      /* Get the data at the next offset.  */
3352*7304104dSAndroid Build Coastguard Worker 	      def = gelf_getverdef (defdata, offset, &defmem);
3353*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (def == NULL))
3354*7304104dSAndroid Build Coastguard Worker 		break;
3355*7304104dSAndroid Build Coastguard Worker 
3356*7304104dSAndroid Build Coastguard Worker 	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
3357*7304104dSAndroid Build Coastguard Worker 
3358*7304104dSAndroid Build Coastguard Worker 	      if (def->vd_next == 0)
3359*7304104dSAndroid Build Coastguard Worker 		break;
3360*7304104dSAndroid Build Coastguard Worker 	      offset += def->vd_next;
3361*7304104dSAndroid Build Coastguard Worker 	    }
3362*7304104dSAndroid Build Coastguard Worker 	}
3363*7304104dSAndroid Build Coastguard Worker       if (needscn != NULL)
3364*7304104dSAndroid Build Coastguard Worker 	{
3365*7304104dSAndroid Build Coastguard Worker 	  unsigned int offset = 0;
3366*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *needdata;
3367*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr needshdrmem;
3368*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *needshdr;
3369*7304104dSAndroid Build Coastguard Worker 
3370*7304104dSAndroid Build Coastguard Worker 	  needdata = elf_getdata (needscn, NULL);
3371*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (needdata == NULL))
3372*7304104dSAndroid Build Coastguard Worker 	    return;
3373*7304104dSAndroid Build Coastguard Worker 
3374*7304104dSAndroid Build Coastguard Worker 	  needshdr = gelf_getshdr (needscn, &needshdrmem);
3375*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (needshdr == NULL))
3376*7304104dSAndroid Build Coastguard Worker 	    return;
3377*7304104dSAndroid Build Coastguard Worker 
3378*7304104dSAndroid Build Coastguard Worker 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
3379*7304104dSAndroid Build Coastguard Worker 	    {
3380*7304104dSAndroid Build Coastguard Worker 	      GElf_Verneed needmem;
3381*7304104dSAndroid Build Coastguard Worker 	      GElf_Verneed *need;
3382*7304104dSAndroid Build Coastguard Worker 	      unsigned int auxoffset;
3383*7304104dSAndroid Build Coastguard Worker 	      int cnt2;
3384*7304104dSAndroid Build Coastguard Worker 
3385*7304104dSAndroid Build Coastguard Worker 	      /* Get the data at the next offset.  */
3386*7304104dSAndroid Build Coastguard Worker 	      need = gelf_getverneed (needdata, offset, &needmem);
3387*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (need == NULL))
3388*7304104dSAndroid Build Coastguard Worker 		break;
3389*7304104dSAndroid Build Coastguard Worker 
3390*7304104dSAndroid Build Coastguard Worker 	      /* Run through the auxiliary entries.  */
3391*7304104dSAndroid Build Coastguard Worker 	      auxoffset = offset + need->vn_aux;
3392*7304104dSAndroid Build Coastguard Worker 	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
3393*7304104dSAndroid Build Coastguard Worker 		{
3394*7304104dSAndroid Build Coastguard Worker 		  GElf_Vernaux auxmem;
3395*7304104dSAndroid Build Coastguard Worker 		  GElf_Vernaux *aux;
3396*7304104dSAndroid Build Coastguard Worker 
3397*7304104dSAndroid Build Coastguard Worker 		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
3398*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (aux == NULL))
3399*7304104dSAndroid Build Coastguard Worker 		    break;
3400*7304104dSAndroid Build Coastguard Worker 
3401*7304104dSAndroid Build Coastguard Worker 		  nvername = MAX (nvername,
3402*7304104dSAndroid Build Coastguard Worker 				  (size_t) (aux->vna_other & 0x7fff));
3403*7304104dSAndroid Build Coastguard Worker 
3404*7304104dSAndroid Build Coastguard Worker 		  if (aux->vna_next == 0)
3405*7304104dSAndroid Build Coastguard Worker 		    break;
3406*7304104dSAndroid Build Coastguard Worker 		  auxoffset += aux->vna_next;
3407*7304104dSAndroid Build Coastguard Worker 		}
3408*7304104dSAndroid Build Coastguard Worker 
3409*7304104dSAndroid Build Coastguard Worker 	      if (need->vn_next == 0)
3410*7304104dSAndroid Build Coastguard Worker 		break;
3411*7304104dSAndroid Build Coastguard Worker 	      offset += need->vn_next;
3412*7304104dSAndroid Build Coastguard Worker 	    }
3413*7304104dSAndroid Build Coastguard Worker 	}
3414*7304104dSAndroid Build Coastguard Worker 
3415*7304104dSAndroid Build Coastguard Worker       /* This is the number of versions we know about.  */
3416*7304104dSAndroid Build Coastguard Worker       ++nvername;
3417*7304104dSAndroid Build Coastguard Worker 
3418*7304104dSAndroid Build Coastguard Worker       /* Allocate the array.  */
3419*7304104dSAndroid Build Coastguard Worker       vername = (const char **) alloca (nvername * sizeof (const char *));
3420*7304104dSAndroid Build Coastguard Worker       memset(vername, 0, nvername * sizeof (const char *));
3421*7304104dSAndroid Build Coastguard Worker       filename = (const char **) alloca (nvername * sizeof (const char *));
3422*7304104dSAndroid Build Coastguard Worker       memset(filename, 0, nvername * sizeof (const char *));
3423*7304104dSAndroid Build Coastguard Worker 
3424*7304104dSAndroid Build Coastguard Worker       /* Run through the data structures again and collect the strings.  */
3425*7304104dSAndroid Build Coastguard Worker       if (defscn != NULL)
3426*7304104dSAndroid Build Coastguard Worker 	{
3427*7304104dSAndroid Build Coastguard Worker 	  /* Run through the version definitions and find the highest
3428*7304104dSAndroid Build Coastguard Worker 	     index.  */
3429*7304104dSAndroid Build Coastguard Worker 	  unsigned int offset = 0;
3430*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *defdata;
3431*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr defshdrmem;
3432*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *defshdr;
3433*7304104dSAndroid Build Coastguard Worker 
3434*7304104dSAndroid Build Coastguard Worker 	  defdata = elf_getdata (defscn, NULL);
3435*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (defdata == NULL))
3436*7304104dSAndroid Build Coastguard Worker 	    return;
3437*7304104dSAndroid Build Coastguard Worker 
3438*7304104dSAndroid Build Coastguard Worker 	  defshdr = gelf_getshdr (defscn, &defshdrmem);
3439*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (defshdr == NULL))
3440*7304104dSAndroid Build Coastguard Worker 	    return;
3441*7304104dSAndroid Build Coastguard Worker 
3442*7304104dSAndroid Build Coastguard Worker 	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
3443*7304104dSAndroid Build Coastguard Worker 	    {
3444*7304104dSAndroid Build Coastguard Worker 
3445*7304104dSAndroid Build Coastguard Worker 	      /* Get the data at the next offset.  */
3446*7304104dSAndroid Build Coastguard Worker 	      GElf_Verdef defmem;
3447*7304104dSAndroid Build Coastguard Worker 	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
3448*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (def == NULL))
3449*7304104dSAndroid Build Coastguard Worker 		break;
3450*7304104dSAndroid Build Coastguard Worker 
3451*7304104dSAndroid Build Coastguard Worker 	      GElf_Verdaux auxmem;
3452*7304104dSAndroid Build Coastguard Worker 	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
3453*7304104dSAndroid Build Coastguard Worker 						   offset + def->vd_aux,
3454*7304104dSAndroid Build Coastguard Worker 						   &auxmem);
3455*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (aux == NULL))
3456*7304104dSAndroid Build Coastguard Worker 		break;
3457*7304104dSAndroid Build Coastguard Worker 
3458*7304104dSAndroid Build Coastguard Worker 	      vername[def->vd_ndx & 0x7fff]
3459*7304104dSAndroid Build Coastguard Worker 		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
3460*7304104dSAndroid Build Coastguard Worker 	      filename[def->vd_ndx & 0x7fff] = NULL;
3461*7304104dSAndroid Build Coastguard Worker 
3462*7304104dSAndroid Build Coastguard Worker 	      if (def->vd_next == 0)
3463*7304104dSAndroid Build Coastguard Worker 		break;
3464*7304104dSAndroid Build Coastguard Worker 	      offset += def->vd_next;
3465*7304104dSAndroid Build Coastguard Worker 	    }
3466*7304104dSAndroid Build Coastguard Worker 	}
3467*7304104dSAndroid Build Coastguard Worker       if (needscn != NULL)
3468*7304104dSAndroid Build Coastguard Worker 	{
3469*7304104dSAndroid Build Coastguard Worker 	  unsigned int offset = 0;
3470*7304104dSAndroid Build Coastguard Worker 
3471*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *needdata = elf_getdata (needscn, NULL);
3472*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr needshdrmem;
3473*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
3474*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (needdata == NULL || needshdr == NULL))
3475*7304104dSAndroid Build Coastguard Worker 	    return;
3476*7304104dSAndroid Build Coastguard Worker 
3477*7304104dSAndroid Build Coastguard Worker 	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
3478*7304104dSAndroid Build Coastguard Worker 	    {
3479*7304104dSAndroid Build Coastguard Worker 	      /* Get the data at the next offset.  */
3480*7304104dSAndroid Build Coastguard Worker 	      GElf_Verneed needmem;
3481*7304104dSAndroid Build Coastguard Worker 	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
3482*7304104dSAndroid Build Coastguard Worker 						    &needmem);
3483*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (need == NULL))
3484*7304104dSAndroid Build Coastguard Worker 		break;
3485*7304104dSAndroid Build Coastguard Worker 
3486*7304104dSAndroid Build Coastguard Worker 	      /* Run through the auxiliary entries.  */
3487*7304104dSAndroid Build Coastguard Worker 	      unsigned int auxoffset = offset + need->vn_aux;
3488*7304104dSAndroid Build Coastguard Worker 	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
3489*7304104dSAndroid Build Coastguard Worker 		{
3490*7304104dSAndroid Build Coastguard Worker 		  GElf_Vernaux auxmem;
3491*7304104dSAndroid Build Coastguard Worker 		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
3492*7304104dSAndroid Build Coastguard Worker 						       &auxmem);
3493*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (aux == NULL))
3494*7304104dSAndroid Build Coastguard Worker 		    break;
3495*7304104dSAndroid Build Coastguard Worker 
3496*7304104dSAndroid Build Coastguard Worker 		  vername[aux->vna_other & 0x7fff]
3497*7304104dSAndroid Build Coastguard Worker 		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
3498*7304104dSAndroid Build Coastguard Worker 		  filename[aux->vna_other & 0x7fff]
3499*7304104dSAndroid Build Coastguard Worker 		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
3500*7304104dSAndroid Build Coastguard Worker 
3501*7304104dSAndroid Build Coastguard Worker 		  if (aux->vna_next == 0)
3502*7304104dSAndroid Build Coastguard Worker 		    break;
3503*7304104dSAndroid Build Coastguard Worker 		  auxoffset += aux->vna_next;
3504*7304104dSAndroid Build Coastguard Worker 		}
3505*7304104dSAndroid Build Coastguard Worker 
3506*7304104dSAndroid Build Coastguard Worker 	      if (need->vn_next == 0)
3507*7304104dSAndroid Build Coastguard Worker 		break;
3508*7304104dSAndroid Build Coastguard Worker 	      offset += need->vn_next;
3509*7304104dSAndroid Build Coastguard Worker 	    }
3510*7304104dSAndroid Build Coastguard Worker 	}
3511*7304104dSAndroid Build Coastguard Worker     }
3512*7304104dSAndroid Build Coastguard Worker   else
3513*7304104dSAndroid Build Coastguard Worker     {
3514*7304104dSAndroid Build Coastguard Worker       vername = NULL;
3515*7304104dSAndroid Build Coastguard Worker       nvername = 1;
3516*7304104dSAndroid Build Coastguard Worker       filename = NULL;
3517*7304104dSAndroid Build Coastguard Worker     }
3518*7304104dSAndroid Build Coastguard Worker 
3519*7304104dSAndroid Build Coastguard Worker   GElf_Shdr glink_mem;
3520*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
3521*7304104dSAndroid Build Coastguard Worker 				   &glink_mem);
3522*7304104dSAndroid Build Coastguard Worker   size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
3523*7304104dSAndroid Build Coastguard Worker   if (glink == NULL)
3524*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("invalid sh_link value in section %zu"),
3525*7304104dSAndroid Build Coastguard Worker 		elf_ndxscn (scn));
3526*7304104dSAndroid Build Coastguard Worker 
3527*7304104dSAndroid Build Coastguard Worker   /* Print the header.  */
3528*7304104dSAndroid Build Coastguard Worker   printf (ngettext ("\
3529*7304104dSAndroid Build Coastguard Worker \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
3530*7304104dSAndroid Build Coastguard Worker 		    "\
3531*7304104dSAndroid Build Coastguard Worker \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
3532*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_size / sh_entsize),
3533*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) elf_ndxscn (scn),
3534*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3535*7304104dSAndroid Build Coastguard Worker 	  (int) (shdr->sh_size / sh_entsize),
3536*7304104dSAndroid Build Coastguard Worker 	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
3537*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_offset,
3538*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) shdr->sh_link,
3539*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3540*7304104dSAndroid Build Coastguard Worker 
3541*7304104dSAndroid Build Coastguard Worker   /* Now we can finally look at the actual contents of this section.  */
3542*7304104dSAndroid Build Coastguard Worker   for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
3543*7304104dSAndroid Build Coastguard Worker     {
3544*7304104dSAndroid Build Coastguard Worker       if (cnt % 2 == 0)
3545*7304104dSAndroid Build Coastguard Worker 	printf ("\n %4d:", cnt);
3546*7304104dSAndroid Build Coastguard Worker 
3547*7304104dSAndroid Build Coastguard Worker       GElf_Versym symmem;
3548*7304104dSAndroid Build Coastguard Worker       GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
3549*7304104dSAndroid Build Coastguard Worker       if (sym == NULL)
3550*7304104dSAndroid Build Coastguard Worker 	break;
3551*7304104dSAndroid Build Coastguard Worker 
3552*7304104dSAndroid Build Coastguard Worker       switch (*sym)
3553*7304104dSAndroid Build Coastguard Worker 	{
3554*7304104dSAndroid Build Coastguard Worker 	  ssize_t n;
3555*7304104dSAndroid Build Coastguard Worker 	case 0:
3556*7304104dSAndroid Build Coastguard Worker 	  fputs_unlocked (_("   0 *local*                     "),
3557*7304104dSAndroid Build Coastguard Worker 			  stdout);
3558*7304104dSAndroid Build Coastguard Worker 	  break;
3559*7304104dSAndroid Build Coastguard Worker 
3560*7304104dSAndroid Build Coastguard Worker 	case 1:
3561*7304104dSAndroid Build Coastguard Worker 	  fputs_unlocked (_("   1 *global*                    "),
3562*7304104dSAndroid Build Coastguard Worker 			  stdout);
3563*7304104dSAndroid Build Coastguard Worker 	  break;
3564*7304104dSAndroid Build Coastguard Worker 
3565*7304104dSAndroid Build Coastguard Worker 	default:
3566*7304104dSAndroid Build Coastguard Worker 	  n = printf ("%4d%c%s",
3567*7304104dSAndroid Build Coastguard Worker 		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
3568*7304104dSAndroid Build Coastguard Worker 		      (vername != NULL
3569*7304104dSAndroid Build Coastguard Worker 		       && (unsigned int) (*sym & 0x7fff) < nvername)
3570*7304104dSAndroid Build Coastguard Worker 		      ? vername[*sym & 0x7fff] : "???");
3571*7304104dSAndroid Build Coastguard Worker 	  if ((unsigned int) (*sym & 0x7fff) < nvername
3572*7304104dSAndroid Build Coastguard Worker 	      && filename != NULL && filename[*sym & 0x7fff] != NULL)
3573*7304104dSAndroid Build Coastguard Worker 	    n += printf ("(%s)", filename[*sym & 0x7fff]);
3574*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s", MAX (0, 33 - (int) n), " ");
3575*7304104dSAndroid Build Coastguard Worker 	  break;
3576*7304104dSAndroid Build Coastguard Worker 	}
3577*7304104dSAndroid Build Coastguard Worker     }
3578*7304104dSAndroid Build Coastguard Worker   putchar_unlocked ('\n');
3579*7304104dSAndroid Build Coastguard Worker }
3580*7304104dSAndroid Build Coastguard Worker 
3581*7304104dSAndroid Build Coastguard Worker 
3582*7304104dSAndroid Build Coastguard Worker static void
print_hash_info(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr,size_t shstrndx,uint_fast32_t maxlength,Elf32_Word nbucket,uint_fast32_t nsyms,uint32_t * lengths,const char * extrastr)3583*7304104dSAndroid Build Coastguard Worker print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
3584*7304104dSAndroid Build Coastguard Worker 		 uint_fast32_t maxlength, Elf32_Word nbucket,
3585*7304104dSAndroid Build Coastguard Worker 		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
3586*7304104dSAndroid Build Coastguard Worker {
3587*7304104dSAndroid Build Coastguard Worker   uint32_t *counts = xcalloc (maxlength + 1, sizeof (uint32_t));
3588*7304104dSAndroid Build Coastguard Worker 
3589*7304104dSAndroid Build Coastguard Worker   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3590*7304104dSAndroid Build Coastguard Worker     ++counts[lengths[cnt]];
3591*7304104dSAndroid Build Coastguard Worker 
3592*7304104dSAndroid Build Coastguard Worker   GElf_Shdr glink_mem;
3593*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
3594*7304104dSAndroid Build Coastguard Worker 					       shdr->sh_link),
3595*7304104dSAndroid Build Coastguard Worker 				   &glink_mem);
3596*7304104dSAndroid Build Coastguard Worker   if (glink == NULL)
3597*7304104dSAndroid Build Coastguard Worker     {
3598*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid sh_link value in section %zu"),
3599*7304104dSAndroid Build Coastguard Worker 	     elf_ndxscn (scn));
3600*7304104dSAndroid Build Coastguard Worker       return;
3601*7304104dSAndroid Build Coastguard Worker     }
3602*7304104dSAndroid Build Coastguard Worker 
3603*7304104dSAndroid Build Coastguard Worker   printf (ngettext ("\
3604*7304104dSAndroid Build Coastguard Worker \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",
3605*7304104dSAndroid Build Coastguard Worker 		    "\
3606*7304104dSAndroid Build Coastguard Worker \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",
3607*7304104dSAndroid Build Coastguard Worker 		    nbucket),
3608*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) elf_ndxscn (scn),
3609*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3610*7304104dSAndroid Build Coastguard Worker 	  (int) nbucket,
3611*7304104dSAndroid Build Coastguard Worker 	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
3612*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_addr,
3613*7304104dSAndroid Build Coastguard Worker 	  shdr->sh_offset,
3614*7304104dSAndroid Build Coastguard Worker 	  (unsigned int) shdr->sh_link,
3615*7304104dSAndroid Build Coastguard Worker 	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
3616*7304104dSAndroid Build Coastguard Worker 
3617*7304104dSAndroid Build Coastguard Worker   if (extrastr != NULL)
3618*7304104dSAndroid Build Coastguard Worker     fputs (extrastr, stdout);
3619*7304104dSAndroid Build Coastguard Worker 
3620*7304104dSAndroid Build Coastguard Worker   if (likely (nbucket > 0))
3621*7304104dSAndroid Build Coastguard Worker     {
3622*7304104dSAndroid Build Coastguard Worker       uint64_t success = 0;
3623*7304104dSAndroid Build Coastguard Worker 
3624*7304104dSAndroid Build Coastguard Worker       /* xgettext:no-c-format */
3625*7304104dSAndroid Build Coastguard Worker       fputs_unlocked (_("\
3626*7304104dSAndroid Build Coastguard Worker  Length  Number  % of total  Coverage\n"), stdout);
3627*7304104dSAndroid Build Coastguard Worker       printf (_("      0  %6" PRIu32 "      %5.1f%%\n"),
3628*7304104dSAndroid Build Coastguard Worker 	      counts[0], (counts[0] * 100.0) / nbucket);
3629*7304104dSAndroid Build Coastguard Worker 
3630*7304104dSAndroid Build Coastguard Worker       uint64_t nzero_counts = 0;
3631*7304104dSAndroid Build Coastguard Worker       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3632*7304104dSAndroid Build Coastguard Worker 	{
3633*7304104dSAndroid Build Coastguard Worker 	  nzero_counts += counts[cnt] * cnt;
3634*7304104dSAndroid Build Coastguard Worker 	  printf (_("\
3635*7304104dSAndroid Build Coastguard Worker %7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
3636*7304104dSAndroid Build Coastguard Worker 		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
3637*7304104dSAndroid Build Coastguard Worker 		  (nzero_counts * 100.0) / nsyms);
3638*7304104dSAndroid Build Coastguard Worker 	}
3639*7304104dSAndroid Build Coastguard Worker 
3640*7304104dSAndroid Build Coastguard Worker       Elf32_Word acc = 0;
3641*7304104dSAndroid Build Coastguard Worker       for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
3642*7304104dSAndroid Build Coastguard Worker 	{
3643*7304104dSAndroid Build Coastguard Worker 	  acc += cnt;
3644*7304104dSAndroid Build Coastguard Worker 	  success += counts[cnt] * acc;
3645*7304104dSAndroid Build Coastguard Worker 	}
3646*7304104dSAndroid Build Coastguard Worker 
3647*7304104dSAndroid Build Coastguard Worker       if (nzero_counts > 0)
3648*7304104dSAndroid Build Coastguard Worker 	printf (_("\
3649*7304104dSAndroid Build Coastguard Worker  Average number of tests:   successful lookup: %f\n\
3650*7304104dSAndroid Build Coastguard Worker 			  unsuccessful lookup: %f\n"),
3651*7304104dSAndroid Build Coastguard Worker 		(double) success / (double) nzero_counts,
3652*7304104dSAndroid Build Coastguard Worker 		(double) nzero_counts / (double) nbucket);
3653*7304104dSAndroid Build Coastguard Worker     }
3654*7304104dSAndroid Build Coastguard Worker 
3655*7304104dSAndroid Build Coastguard Worker   free (counts);
3656*7304104dSAndroid Build Coastguard Worker }
3657*7304104dSAndroid Build Coastguard Worker 
3658*7304104dSAndroid Build Coastguard Worker 
3659*7304104dSAndroid Build Coastguard Worker /* This function handles the traditional System V-style hash table format.  */
3660*7304104dSAndroid Build Coastguard Worker static void
handle_sysv_hash(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr,size_t shstrndx)3661*7304104dSAndroid Build Coastguard Worker handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3662*7304104dSAndroid Build Coastguard Worker {
3663*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
3664*7304104dSAndroid Build Coastguard Worker   if (unlikely (data == NULL))
3665*7304104dSAndroid Build Coastguard Worker     {
3666*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get data for section %d: %s"),
3667*7304104dSAndroid Build Coastguard Worker 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
3668*7304104dSAndroid Build Coastguard Worker       return;
3669*7304104dSAndroid Build Coastguard Worker     }
3670*7304104dSAndroid Build Coastguard Worker 
3671*7304104dSAndroid Build Coastguard Worker   if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
3672*7304104dSAndroid Build Coastguard Worker     {
3673*7304104dSAndroid Build Coastguard Worker     invalid_data:
3674*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid data in sysv.hash section %d"),
3675*7304104dSAndroid Build Coastguard Worker 	     (int) elf_ndxscn (scn));
3676*7304104dSAndroid Build Coastguard Worker       return;
3677*7304104dSAndroid Build Coastguard Worker     }
3678*7304104dSAndroid Build Coastguard Worker 
3679*7304104dSAndroid Build Coastguard Worker   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3680*7304104dSAndroid Build Coastguard Worker   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
3681*7304104dSAndroid Build Coastguard Worker 
3682*7304104dSAndroid Build Coastguard Worker   uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
3683*7304104dSAndroid Build Coastguard Worker   if (used_buf > data->d_size)
3684*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
3685*7304104dSAndroid Build Coastguard Worker 
3686*7304104dSAndroid Build Coastguard Worker   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
3687*7304104dSAndroid Build Coastguard Worker   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
3688*7304104dSAndroid Build Coastguard Worker 
3689*7304104dSAndroid Build Coastguard Worker   uint32_t *lengths = xcalloc (nbucket, sizeof (uint32_t));
3690*7304104dSAndroid Build Coastguard Worker 
3691*7304104dSAndroid Build Coastguard Worker   uint_fast32_t maxlength = 0;
3692*7304104dSAndroid Build Coastguard Worker   uint_fast32_t nsyms = 0;
3693*7304104dSAndroid Build Coastguard Worker   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3694*7304104dSAndroid Build Coastguard Worker     {
3695*7304104dSAndroid Build Coastguard Worker       Elf32_Word inner = bucket[cnt];
3696*7304104dSAndroid Build Coastguard Worker       Elf32_Word chain_len = 0;
3697*7304104dSAndroid Build Coastguard Worker       while (inner > 0 && inner < nchain)
3698*7304104dSAndroid Build Coastguard Worker 	{
3699*7304104dSAndroid Build Coastguard Worker 	  ++nsyms;
3700*7304104dSAndroid Build Coastguard Worker 	  ++chain_len;
3701*7304104dSAndroid Build Coastguard Worker 	  if (chain_len > nchain)
3702*7304104dSAndroid Build Coastguard Worker 	    {
3703*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("invalid chain in sysv.hash section %d"),
3704*7304104dSAndroid Build Coastguard Worker 		     (int) elf_ndxscn (scn));
3705*7304104dSAndroid Build Coastguard Worker 	      free (lengths);
3706*7304104dSAndroid Build Coastguard Worker 	      return;
3707*7304104dSAndroid Build Coastguard Worker 	    }
3708*7304104dSAndroid Build Coastguard Worker 	  if (maxlength < ++lengths[cnt])
3709*7304104dSAndroid Build Coastguard Worker 	    ++maxlength;
3710*7304104dSAndroid Build Coastguard Worker 
3711*7304104dSAndroid Build Coastguard Worker 	  inner = chain[inner];
3712*7304104dSAndroid Build Coastguard Worker 	}
3713*7304104dSAndroid Build Coastguard Worker     }
3714*7304104dSAndroid Build Coastguard Worker 
3715*7304104dSAndroid Build Coastguard Worker   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3716*7304104dSAndroid Build Coastguard Worker 		   lengths, NULL);
3717*7304104dSAndroid Build Coastguard Worker 
3718*7304104dSAndroid Build Coastguard Worker   free (lengths);
3719*7304104dSAndroid Build Coastguard Worker }
3720*7304104dSAndroid Build Coastguard Worker 
3721*7304104dSAndroid Build Coastguard Worker 
3722*7304104dSAndroid Build Coastguard Worker /* This function handles the incorrect, System V-style hash table
3723*7304104dSAndroid Build Coastguard Worker    format some 64-bit architectures use.  */
3724*7304104dSAndroid Build Coastguard Worker static void
handle_sysv_hash64(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr,size_t shstrndx)3725*7304104dSAndroid Build Coastguard Worker handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3726*7304104dSAndroid Build Coastguard Worker {
3727*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
3728*7304104dSAndroid Build Coastguard Worker   if (unlikely (data == NULL))
3729*7304104dSAndroid Build Coastguard Worker     {
3730*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get data for section %d: %s"),
3731*7304104dSAndroid Build Coastguard Worker 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
3732*7304104dSAndroid Build Coastguard Worker       return;
3733*7304104dSAndroid Build Coastguard Worker     }
3734*7304104dSAndroid Build Coastguard Worker 
3735*7304104dSAndroid Build Coastguard Worker   if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
3736*7304104dSAndroid Build Coastguard Worker     {
3737*7304104dSAndroid Build Coastguard Worker     invalid_data:
3738*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid data in sysv.hash64 section %d"),
3739*7304104dSAndroid Build Coastguard Worker 	     (int) elf_ndxscn (scn));
3740*7304104dSAndroid Build Coastguard Worker       return;
3741*7304104dSAndroid Build Coastguard Worker     }
3742*7304104dSAndroid Build Coastguard Worker 
3743*7304104dSAndroid Build Coastguard Worker   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
3744*7304104dSAndroid Build Coastguard Worker   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
3745*7304104dSAndroid Build Coastguard Worker 
3746*7304104dSAndroid Build Coastguard Worker   uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
3747*7304104dSAndroid Build Coastguard Worker   if (maxwords < 2
3748*7304104dSAndroid Build Coastguard Worker       || maxwords - 2 < nbucket
3749*7304104dSAndroid Build Coastguard Worker       || maxwords - 2 - nbucket < nchain)
3750*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
3751*7304104dSAndroid Build Coastguard Worker 
3752*7304104dSAndroid Build Coastguard Worker   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
3753*7304104dSAndroid Build Coastguard Worker   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
3754*7304104dSAndroid Build Coastguard Worker 
3755*7304104dSAndroid Build Coastguard Worker   uint32_t *lengths = xcalloc (nbucket, sizeof (uint32_t));
3756*7304104dSAndroid Build Coastguard Worker 
3757*7304104dSAndroid Build Coastguard Worker   uint_fast32_t maxlength = 0;
3758*7304104dSAndroid Build Coastguard Worker   uint_fast32_t nsyms = 0;
3759*7304104dSAndroid Build Coastguard Worker   for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
3760*7304104dSAndroid Build Coastguard Worker     {
3761*7304104dSAndroid Build Coastguard Worker       Elf64_Xword inner = bucket[cnt];
3762*7304104dSAndroid Build Coastguard Worker       Elf64_Xword chain_len = 0;
3763*7304104dSAndroid Build Coastguard Worker       while (inner > 0 && inner < nchain)
3764*7304104dSAndroid Build Coastguard Worker 	{
3765*7304104dSAndroid Build Coastguard Worker 	  ++nsyms;
3766*7304104dSAndroid Build Coastguard Worker 	  ++chain_len;
3767*7304104dSAndroid Build Coastguard Worker 	  if (chain_len > nchain)
3768*7304104dSAndroid Build Coastguard Worker 	    {
3769*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("invalid chain in sysv.hash64 section %d"),
3770*7304104dSAndroid Build Coastguard Worker 		     (int) elf_ndxscn (scn));
3771*7304104dSAndroid Build Coastguard Worker 	      free (lengths);
3772*7304104dSAndroid Build Coastguard Worker 	      return;
3773*7304104dSAndroid Build Coastguard Worker 	    }
3774*7304104dSAndroid Build Coastguard Worker 	  if (maxlength < ++lengths[cnt])
3775*7304104dSAndroid Build Coastguard Worker 	    ++maxlength;
3776*7304104dSAndroid Build Coastguard Worker 
3777*7304104dSAndroid Build Coastguard Worker 	  inner = chain[inner];
3778*7304104dSAndroid Build Coastguard Worker 	}
3779*7304104dSAndroid Build Coastguard Worker     }
3780*7304104dSAndroid Build Coastguard Worker 
3781*7304104dSAndroid Build Coastguard Worker   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3782*7304104dSAndroid Build Coastguard Worker 		   lengths, NULL);
3783*7304104dSAndroid Build Coastguard Worker 
3784*7304104dSAndroid Build Coastguard Worker   free (lengths);
3785*7304104dSAndroid Build Coastguard Worker }
3786*7304104dSAndroid Build Coastguard Worker 
3787*7304104dSAndroid Build Coastguard Worker 
3788*7304104dSAndroid Build Coastguard Worker /* This function handles the GNU-style hash table format.  */
3789*7304104dSAndroid Build Coastguard Worker static void
handle_gnu_hash(Ebl * ebl,Elf_Scn * scn,GElf_Shdr * shdr,size_t shstrndx)3790*7304104dSAndroid Build Coastguard Worker handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
3791*7304104dSAndroid Build Coastguard Worker {
3792*7304104dSAndroid Build Coastguard Worker   uint32_t *lengths = NULL;
3793*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
3794*7304104dSAndroid Build Coastguard Worker   if (unlikely (data == NULL))
3795*7304104dSAndroid Build Coastguard Worker     {
3796*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get data for section %d: %s"),
3797*7304104dSAndroid Build Coastguard Worker 	     (int) elf_ndxscn (scn), elf_errmsg (-1));
3798*7304104dSAndroid Build Coastguard Worker       return;
3799*7304104dSAndroid Build Coastguard Worker     }
3800*7304104dSAndroid Build Coastguard Worker 
3801*7304104dSAndroid Build Coastguard Worker   if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
3802*7304104dSAndroid Build Coastguard Worker     {
3803*7304104dSAndroid Build Coastguard Worker     invalid_data:
3804*7304104dSAndroid Build Coastguard Worker       free (lengths);
3805*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid data in gnu.hash section %d"),
3806*7304104dSAndroid Build Coastguard Worker 	     (int) elf_ndxscn (scn));
3807*7304104dSAndroid Build Coastguard Worker       return;
3808*7304104dSAndroid Build Coastguard Worker     }
3809*7304104dSAndroid Build Coastguard Worker 
3810*7304104dSAndroid Build Coastguard Worker   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
3811*7304104dSAndroid Build Coastguard Worker   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
3812*7304104dSAndroid Build Coastguard Worker 
3813*7304104dSAndroid Build Coastguard Worker   /* Next comes the size of the bitmap.  It's measured in words for
3814*7304104dSAndroid Build Coastguard Worker      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
3815*7304104dSAndroid Build Coastguard Worker      64 bit archs.  There is always a bloom filter present, so zero is
3816*7304104dSAndroid Build Coastguard Worker      an invalid value.  */
3817*7304104dSAndroid Build Coastguard Worker   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
3818*7304104dSAndroid Build Coastguard Worker   if (gelf_getclass (ebl->elf) == ELFCLASS64)
3819*7304104dSAndroid Build Coastguard Worker     bitmask_words *= 2;
3820*7304104dSAndroid Build Coastguard Worker 
3821*7304104dSAndroid Build Coastguard Worker   if (bitmask_words == 0)
3822*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
3823*7304104dSAndroid Build Coastguard Worker 
3824*7304104dSAndroid Build Coastguard Worker   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
3825*7304104dSAndroid Build Coastguard Worker 
3826*7304104dSAndroid Build Coastguard Worker   /* Is there still room for the sym chain?
3827*7304104dSAndroid Build Coastguard Worker      Use uint64_t calculation to prevent 32bit overflow.  */
3828*7304104dSAndroid Build Coastguard Worker   uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
3829*7304104dSAndroid Build Coastguard Worker   uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
3830*7304104dSAndroid Build Coastguard Worker   if (used_buf > data->d_size)
3831*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
3832*7304104dSAndroid Build Coastguard Worker 
3833*7304104dSAndroid Build Coastguard Worker   lengths = xcalloc (nbucket, sizeof (uint32_t));
3834*7304104dSAndroid Build Coastguard Worker 
3835*7304104dSAndroid Build Coastguard Worker   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
3836*7304104dSAndroid Build Coastguard Worker   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
3837*7304104dSAndroid Build Coastguard Worker   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
3838*7304104dSAndroid Build Coastguard Worker 						    + nbucket];
3839*7304104dSAndroid Build Coastguard Worker 
3840*7304104dSAndroid Build Coastguard Worker   /* Compute distribution of chain lengths.  */
3841*7304104dSAndroid Build Coastguard Worker   uint_fast32_t maxlength = 0;
3842*7304104dSAndroid Build Coastguard Worker   uint_fast32_t nsyms = 0;
3843*7304104dSAndroid Build Coastguard Worker   for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
3844*7304104dSAndroid Build Coastguard Worker     if (bucket[cnt] != 0)
3845*7304104dSAndroid Build Coastguard Worker       {
3846*7304104dSAndroid Build Coastguard Worker 	Elf32_Word inner = bucket[cnt] - symbias;
3847*7304104dSAndroid Build Coastguard Worker 	do
3848*7304104dSAndroid Build Coastguard Worker 	  {
3849*7304104dSAndroid Build Coastguard Worker 	    ++nsyms;
3850*7304104dSAndroid Build Coastguard Worker 	    if (maxlength < ++lengths[cnt])
3851*7304104dSAndroid Build Coastguard Worker 	      ++maxlength;
3852*7304104dSAndroid Build Coastguard Worker 	    if (inner >= max_nsyms)
3853*7304104dSAndroid Build Coastguard Worker 	      goto invalid_data;
3854*7304104dSAndroid Build Coastguard Worker 	  }
3855*7304104dSAndroid Build Coastguard Worker 	while ((chain[inner++] & 1) == 0);
3856*7304104dSAndroid Build Coastguard Worker       }
3857*7304104dSAndroid Build Coastguard Worker 
3858*7304104dSAndroid Build Coastguard Worker   /* Count bits in bitmask.  */
3859*7304104dSAndroid Build Coastguard Worker   uint_fast32_t nbits = 0;
3860*7304104dSAndroid Build Coastguard Worker   for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
3861*7304104dSAndroid Build Coastguard Worker     {
3862*7304104dSAndroid Build Coastguard Worker       uint_fast32_t word = bitmask[cnt];
3863*7304104dSAndroid Build Coastguard Worker 
3864*7304104dSAndroid Build Coastguard Worker       word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
3865*7304104dSAndroid Build Coastguard Worker       word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
3866*7304104dSAndroid Build Coastguard Worker       word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
3867*7304104dSAndroid Build Coastguard Worker       word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
3868*7304104dSAndroid Build Coastguard Worker       nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
3869*7304104dSAndroid Build Coastguard Worker     }
3870*7304104dSAndroid Build Coastguard Worker 
3871*7304104dSAndroid Build Coastguard Worker   char *str = xasprintf (_("\
3872*7304104dSAndroid Build Coastguard Worker  Symbol Bias: %u\n\
3873*7304104dSAndroid Build Coastguard Worker  Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
3874*7304104dSAndroid Build Coastguard Worker 			 (unsigned int) symbias,
3875*7304104dSAndroid Build Coastguard Worker 			 bitmask_words * sizeof (Elf32_Word),
3876*7304104dSAndroid Build Coastguard Worker 			 ((nbits * 100 + 50)
3877*7304104dSAndroid Build Coastguard Worker 			  / (uint_fast32_t) (bitmask_words
3878*7304104dSAndroid Build Coastguard Worker 					      * sizeof (Elf32_Word) * 8)),
3879*7304104dSAndroid Build Coastguard Worker 			  (unsigned int) shift);
3880*7304104dSAndroid Build Coastguard Worker 
3881*7304104dSAndroid Build Coastguard Worker   print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
3882*7304104dSAndroid Build Coastguard Worker 		   lengths, str);
3883*7304104dSAndroid Build Coastguard Worker 
3884*7304104dSAndroid Build Coastguard Worker   free (str);
3885*7304104dSAndroid Build Coastguard Worker   free (lengths);
3886*7304104dSAndroid Build Coastguard Worker }
3887*7304104dSAndroid Build Coastguard Worker 
3888*7304104dSAndroid Build Coastguard Worker 
3889*7304104dSAndroid Build Coastguard Worker /* Find the symbol table(s).  For this we have to search through the
3890*7304104dSAndroid Build Coastguard Worker    section table.  */
3891*7304104dSAndroid Build Coastguard Worker static void
handle_hash(Ebl * ebl)3892*7304104dSAndroid Build Coastguard Worker handle_hash (Ebl *ebl)
3893*7304104dSAndroid Build Coastguard Worker {
3894*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
3895*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
3896*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3897*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
3898*7304104dSAndroid Build Coastguard Worker 
3899*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
3900*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3901*7304104dSAndroid Build Coastguard Worker     {
3902*7304104dSAndroid Build Coastguard Worker       /* Handle the section if it is a symbol table.  */
3903*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
3904*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3905*7304104dSAndroid Build Coastguard Worker 
3906*7304104dSAndroid Build Coastguard Worker       if (likely (shdr != NULL))
3907*7304104dSAndroid Build Coastguard Worker 	{
3908*7304104dSAndroid Build Coastguard Worker 	  if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
3909*7304104dSAndroid Build Coastguard Worker 	      && (shdr->sh_flags & SHF_COMPRESSED) != 0)
3910*7304104dSAndroid Build Coastguard Worker 	    {
3911*7304104dSAndroid Build Coastguard Worker 	      if (elf_compress (scn, 0, 0) < 0)
3912*7304104dSAndroid Build Coastguard Worker 		printf ("WARNING: %s [%zd]\n",
3913*7304104dSAndroid Build Coastguard Worker 			_("Couldn't uncompress section"),
3914*7304104dSAndroid Build Coastguard Worker 			elf_ndxscn (scn));
3915*7304104dSAndroid Build Coastguard Worker 	      shdr = gelf_getshdr (scn, &shdr_mem);
3916*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (shdr == NULL))
3917*7304104dSAndroid Build Coastguard Worker 		error_exit (0, _("cannot get section [%zd] header: %s"),
3918*7304104dSAndroid Build Coastguard Worker 			    elf_ndxscn (scn), elf_errmsg (-1));
3919*7304104dSAndroid Build Coastguard Worker 	    }
3920*7304104dSAndroid Build Coastguard Worker 
3921*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_type == SHT_HASH)
3922*7304104dSAndroid Build Coastguard Worker 	    {
3923*7304104dSAndroid Build Coastguard Worker 	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
3924*7304104dSAndroid Build Coastguard Worker 		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
3925*7304104dSAndroid Build Coastguard Worker 	      else
3926*7304104dSAndroid Build Coastguard Worker 		handle_sysv_hash (ebl, scn, shdr, shstrndx);
3927*7304104dSAndroid Build Coastguard Worker 	    }
3928*7304104dSAndroid Build Coastguard Worker 	  else if (shdr->sh_type == SHT_GNU_HASH)
3929*7304104dSAndroid Build Coastguard Worker 	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
3930*7304104dSAndroid Build Coastguard Worker 	}
3931*7304104dSAndroid Build Coastguard Worker     }
3932*7304104dSAndroid Build Coastguard Worker }
3933*7304104dSAndroid Build Coastguard Worker 
3934*7304104dSAndroid Build Coastguard Worker 
3935*7304104dSAndroid Build Coastguard Worker static void
print_liblist(Ebl * ebl)3936*7304104dSAndroid Build Coastguard Worker print_liblist (Ebl *ebl)
3937*7304104dSAndroid Build Coastguard Worker {
3938*7304104dSAndroid Build Coastguard Worker   /* Find the library list sections.  For this we have to search
3939*7304104dSAndroid Build Coastguard Worker      through the section table.  */
3940*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
3941*7304104dSAndroid Build Coastguard Worker 
3942*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
3943*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
3944*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
3945*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
3946*7304104dSAndroid Build Coastguard Worker 
3947*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
3948*7304104dSAndroid Build Coastguard Worker     {
3949*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
3950*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3951*7304104dSAndroid Build Coastguard Worker 
3952*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
3953*7304104dSAndroid Build Coastguard Worker 	{
3954*7304104dSAndroid Build Coastguard Worker 	  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
3955*7304104dSAndroid Build Coastguard Worker 	  int nentries = shdr->sh_size / sh_entsize;
3956*7304104dSAndroid Build Coastguard Worker 	  printf (ngettext ("\
3957*7304104dSAndroid Build Coastguard Worker \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
3958*7304104dSAndroid Build Coastguard Worker 			    "\
3959*7304104dSAndroid Build Coastguard Worker \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
3960*7304104dSAndroid Build Coastguard Worker 			    nentries),
3961*7304104dSAndroid Build Coastguard Worker 		  elf_ndxscn (scn),
3962*7304104dSAndroid Build Coastguard Worker 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
3963*7304104dSAndroid Build Coastguard Worker 		  shdr->sh_offset,
3964*7304104dSAndroid Build Coastguard Worker 		  nentries);
3965*7304104dSAndroid Build Coastguard Worker 
3966*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *data = elf_getdata (scn, NULL);
3967*7304104dSAndroid Build Coastguard Worker 	  if (data == NULL)
3968*7304104dSAndroid Build Coastguard Worker 	    return;
3969*7304104dSAndroid Build Coastguard Worker 
3970*7304104dSAndroid Build Coastguard Worker 	  puts (_("\
3971*7304104dSAndroid Build Coastguard Worker        Library                       Time Stamp          Checksum Version Flags"));
3972*7304104dSAndroid Build Coastguard Worker 
3973*7304104dSAndroid Build Coastguard Worker 	  for (int cnt = 0; cnt < nentries; ++cnt)
3974*7304104dSAndroid Build Coastguard Worker 	    {
3975*7304104dSAndroid Build Coastguard Worker 	      GElf_Lib lib_mem;
3976*7304104dSAndroid Build Coastguard Worker 	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
3977*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (lib == NULL))
3978*7304104dSAndroid Build Coastguard Worker 		continue;
3979*7304104dSAndroid Build Coastguard Worker 
3980*7304104dSAndroid Build Coastguard Worker 	      time_t t = (time_t) lib->l_time_stamp;
3981*7304104dSAndroid Build Coastguard Worker 	      struct tm *tm = gmtime (&t);
3982*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (tm == NULL))
3983*7304104dSAndroid Build Coastguard Worker 		continue;
3984*7304104dSAndroid Build Coastguard Worker 
3985*7304104dSAndroid Build Coastguard Worker 	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
3986*7304104dSAndroid Build Coastguard Worker 		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
3987*7304104dSAndroid Build Coastguard Worker 		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3988*7304104dSAndroid Build Coastguard Worker 		      tm->tm_hour, tm->tm_min, tm->tm_sec,
3989*7304104dSAndroid Build Coastguard Worker 		      (unsigned int) lib->l_checksum,
3990*7304104dSAndroid Build Coastguard Worker 		      (unsigned int) lib->l_version,
3991*7304104dSAndroid Build Coastguard Worker 		      (unsigned int) lib->l_flags);
3992*7304104dSAndroid Build Coastguard Worker 	    }
3993*7304104dSAndroid Build Coastguard Worker 	}
3994*7304104dSAndroid Build Coastguard Worker     }
3995*7304104dSAndroid Build Coastguard Worker }
3996*7304104dSAndroid Build Coastguard Worker 
3997*7304104dSAndroid Build Coastguard Worker static inline size_t
left(Elf_Data * data,const unsigned char * p)3998*7304104dSAndroid Build Coastguard Worker left (Elf_Data *data,
3999*7304104dSAndroid Build Coastguard Worker       const unsigned char *p)
4000*7304104dSAndroid Build Coastguard Worker {
4001*7304104dSAndroid Build Coastguard Worker   return (const unsigned char *) data->d_buf + data->d_size - p;
4002*7304104dSAndroid Build Coastguard Worker }
4003*7304104dSAndroid Build Coastguard Worker 
4004*7304104dSAndroid Build Coastguard Worker static void
print_attributes(Ebl * ebl,const GElf_Ehdr * ehdr)4005*7304104dSAndroid Build Coastguard Worker print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
4006*7304104dSAndroid Build Coastguard Worker {
4007*7304104dSAndroid Build Coastguard Worker   /* Find the object attributes sections.  For this we have to search
4008*7304104dSAndroid Build Coastguard Worker      through the section table.  */
4009*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
4010*7304104dSAndroid Build Coastguard Worker 
4011*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
4012*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
4013*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
4014*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
4015*7304104dSAndroid Build Coastguard Worker 
4016*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
4017*7304104dSAndroid Build Coastguard Worker     {
4018*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
4019*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
4020*7304104dSAndroid Build Coastguard Worker 
4021*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
4022*7304104dSAndroid Build Coastguard Worker 			   && (shdr->sh_type != SHT_ARM_ATTRIBUTES
4023*7304104dSAndroid Build Coastguard Worker 			       || ehdr->e_machine != EM_ARM)
4024*7304104dSAndroid Build Coastguard Worker 			   && (shdr->sh_type != SHT_CSKY_ATTRIBUTES
4025*7304104dSAndroid Build Coastguard Worker 			       || ehdr->e_machine != EM_CSKY)
4026*7304104dSAndroid Build Coastguard Worker 			   && (shdr->sh_type != SHT_RISCV_ATTRIBUTES
4027*7304104dSAndroid Build Coastguard Worker 			       || ehdr->e_machine != EM_RISCV)))
4028*7304104dSAndroid Build Coastguard Worker 	continue;
4029*7304104dSAndroid Build Coastguard Worker 
4030*7304104dSAndroid Build Coastguard Worker       printf (_("\
4031*7304104dSAndroid Build Coastguard Worker \nObject attributes section [%2zu] '%s' of %" PRIu64
4032*7304104dSAndroid Build Coastguard Worker 		       " bytes at offset %#0" PRIx64 ":\n"),
4033*7304104dSAndroid Build Coastguard Worker 	      elf_ndxscn (scn),
4034*7304104dSAndroid Build Coastguard Worker 	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
4035*7304104dSAndroid Build Coastguard Worker 	      shdr->sh_size, shdr->sh_offset);
4036*7304104dSAndroid Build Coastguard Worker 
4037*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_rawdata (scn, NULL);
4038*7304104dSAndroid Build Coastguard Worker       if (unlikely (data == NULL || data->d_size == 0))
4039*7304104dSAndroid Build Coastguard Worker 	return;
4040*7304104dSAndroid Build Coastguard Worker 
4041*7304104dSAndroid Build Coastguard Worker       const unsigned char *p = data->d_buf;
4042*7304104dSAndroid Build Coastguard Worker 
4043*7304104dSAndroid Build Coastguard Worker       /* There is only one 'version', A.  */
4044*7304104dSAndroid Build Coastguard Worker       if (unlikely (*p++ != 'A'))
4045*7304104dSAndroid Build Coastguard Worker 	return;
4046*7304104dSAndroid Build Coastguard Worker 
4047*7304104dSAndroid Build Coastguard Worker       fputs_unlocked (_("  Owner          Size\n"), stdout);
4048*7304104dSAndroid Build Coastguard Worker 
4049*7304104dSAndroid Build Coastguard Worker       /* Loop over the sections.  */
4050*7304104dSAndroid Build Coastguard Worker       while (left (data, p) >= 4)
4051*7304104dSAndroid Build Coastguard Worker 	{
4052*7304104dSAndroid Build Coastguard Worker 	  /* Section length.  */
4053*7304104dSAndroid Build Coastguard Worker 	  uint32_t len;
4054*7304104dSAndroid Build Coastguard Worker 	  memcpy (&len, p, sizeof len);
4055*7304104dSAndroid Build Coastguard Worker 
4056*7304104dSAndroid Build Coastguard Worker 	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
4057*7304104dSAndroid Build Coastguard Worker 	    CONVERT (len);
4058*7304104dSAndroid Build Coastguard Worker 
4059*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (len > left (data, p)))
4060*7304104dSAndroid Build Coastguard Worker 	    break;
4061*7304104dSAndroid Build Coastguard Worker 
4062*7304104dSAndroid Build Coastguard Worker 	  /* Section vendor name.  */
4063*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *name = p + sizeof len;
4064*7304104dSAndroid Build Coastguard Worker 	  p += len;
4065*7304104dSAndroid Build Coastguard Worker 
4066*7304104dSAndroid Build Coastguard Worker 	  unsigned const char *q = memchr (name, '\0', len);
4067*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (q == NULL))
4068*7304104dSAndroid Build Coastguard Worker 	    break;
4069*7304104dSAndroid Build Coastguard Worker 	  ++q;
4070*7304104dSAndroid Build Coastguard Worker 
4071*7304104dSAndroid Build Coastguard Worker 	  printf (_("  %-13s  %4" PRIu32 "\n"), name, len);
4072*7304104dSAndroid Build Coastguard Worker 
4073*7304104dSAndroid Build Coastguard Worker 	  bool gnu_vendor = (q - name == sizeof "gnu"
4074*7304104dSAndroid Build Coastguard Worker 			     && !memcmp (name, "gnu", sizeof "gnu"));
4075*7304104dSAndroid Build Coastguard Worker 
4076*7304104dSAndroid Build Coastguard Worker 	  /* Loop over subsections.  */
4077*7304104dSAndroid Build Coastguard Worker 	  if (shdr->sh_type != SHT_GNU_ATTRIBUTES
4078*7304104dSAndroid Build Coastguard Worker 	      || gnu_vendor)
4079*7304104dSAndroid Build Coastguard Worker 	    while (q < p)
4080*7304104dSAndroid Build Coastguard Worker 	      {
4081*7304104dSAndroid Build Coastguard Worker 		const unsigned char *const sub = q;
4082*7304104dSAndroid Build Coastguard Worker 
4083*7304104dSAndroid Build Coastguard Worker 		unsigned int subsection_tag;
4084*7304104dSAndroid Build Coastguard Worker 		get_uleb128 (subsection_tag, q, p);
4085*7304104dSAndroid Build Coastguard Worker 		if (unlikely (q >= p))
4086*7304104dSAndroid Build Coastguard Worker 		  break;
4087*7304104dSAndroid Build Coastguard Worker 
4088*7304104dSAndroid Build Coastguard Worker 		uint32_t subsection_len;
4089*7304104dSAndroid Build Coastguard Worker 		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
4090*7304104dSAndroid Build Coastguard Worker 		  break;
4091*7304104dSAndroid Build Coastguard Worker 
4092*7304104dSAndroid Build Coastguard Worker 		memcpy (&subsection_len, q, sizeof subsection_len);
4093*7304104dSAndroid Build Coastguard Worker 
4094*7304104dSAndroid Build Coastguard Worker 		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
4095*7304104dSAndroid Build Coastguard Worker 		  CONVERT (subsection_len);
4096*7304104dSAndroid Build Coastguard Worker 
4097*7304104dSAndroid Build Coastguard Worker 		/* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
4098*7304104dSAndroid Build Coastguard Worker 		if (unlikely (subsection_len == 0
4099*7304104dSAndroid Build Coastguard Worker 			      || subsection_len >= (uint32_t) PTRDIFF_MAX
4100*7304104dSAndroid Build Coastguard Worker 			      || p - sub < (ptrdiff_t) subsection_len))
4101*7304104dSAndroid Build Coastguard Worker 		  break;
4102*7304104dSAndroid Build Coastguard Worker 
4103*7304104dSAndroid Build Coastguard Worker 		const unsigned char *r = q + sizeof subsection_len;
4104*7304104dSAndroid Build Coastguard Worker 		q = sub + subsection_len;
4105*7304104dSAndroid Build Coastguard Worker 
4106*7304104dSAndroid Build Coastguard Worker 		switch (subsection_tag)
4107*7304104dSAndroid Build Coastguard Worker 		  {
4108*7304104dSAndroid Build Coastguard Worker 		  default:
4109*7304104dSAndroid Build Coastguard Worker 		    /* Unknown subsection, print and skip.  */
4110*7304104dSAndroid Build Coastguard Worker 		    printf (_("    %-4u %12" PRIu32 "\n"),
4111*7304104dSAndroid Build Coastguard Worker 			    subsection_tag, subsection_len);
4112*7304104dSAndroid Build Coastguard Worker 		    break;
4113*7304104dSAndroid Build Coastguard Worker 
4114*7304104dSAndroid Build Coastguard Worker 		  case 1:	/* Tag_File */
4115*7304104dSAndroid Build Coastguard Worker 		    printf (_("    File: %11" PRIu32 "\n"),
4116*7304104dSAndroid Build Coastguard Worker 			    subsection_len);
4117*7304104dSAndroid Build Coastguard Worker 
4118*7304104dSAndroid Build Coastguard Worker 		    while (r < q)
4119*7304104dSAndroid Build Coastguard Worker 		      {
4120*7304104dSAndroid Build Coastguard Worker 			unsigned int tag;
4121*7304104dSAndroid Build Coastguard Worker 			get_uleb128 (tag, r, q);
4122*7304104dSAndroid Build Coastguard Worker 			if (unlikely (r >= q))
4123*7304104dSAndroid Build Coastguard Worker 			  break;
4124*7304104dSAndroid Build Coastguard Worker 
4125*7304104dSAndroid Build Coastguard Worker 			/* GNU style tags have either a uleb128 value,
4126*7304104dSAndroid Build Coastguard Worker 			   when lowest bit is not set, or a string
4127*7304104dSAndroid Build Coastguard Worker 			   when the lowest bit is set.
4128*7304104dSAndroid Build Coastguard Worker 			   "compatibility" (32) is special.  It has
4129*7304104dSAndroid Build Coastguard Worker 			   both a string and a uleb128 value.  For
4130*7304104dSAndroid Build Coastguard Worker 			   non-gnu we assume 6 till 31 only take ints.
4131*7304104dSAndroid Build Coastguard Worker 			   XXX see arm backend, do we need a separate
4132*7304104dSAndroid Build Coastguard Worker 			   hook?  */
4133*7304104dSAndroid Build Coastguard Worker 			uint64_t value = 0;
4134*7304104dSAndroid Build Coastguard Worker 			const char *string = NULL;
4135*7304104dSAndroid Build Coastguard Worker 			if (tag == 32 || (tag & 1) == 0
4136*7304104dSAndroid Build Coastguard Worker 			    || (! gnu_vendor && (tag > 5 && tag < 32)))
4137*7304104dSAndroid Build Coastguard Worker 			  {
4138*7304104dSAndroid Build Coastguard Worker 			    // Note r >= q check above.
4139*7304104dSAndroid Build Coastguard Worker 			    get_uleb128 (value, r, q);
4140*7304104dSAndroid Build Coastguard Worker 			    if (r > q)
4141*7304104dSAndroid Build Coastguard Worker 			      break;
4142*7304104dSAndroid Build Coastguard Worker 			  }
4143*7304104dSAndroid Build Coastguard Worker 			if (tag == 32
4144*7304104dSAndroid Build Coastguard Worker 			    || ((tag & 1) != 0
4145*7304104dSAndroid Build Coastguard Worker 				&& (gnu_vendor
4146*7304104dSAndroid Build Coastguard Worker 				    || (! gnu_vendor && tag > 32)))
4147*7304104dSAndroid Build Coastguard Worker 			    || (! gnu_vendor && tag > 3 && tag < 6))
4148*7304104dSAndroid Build Coastguard Worker 			  {
4149*7304104dSAndroid Build Coastguard Worker 			    string = (const char *) r;
4150*7304104dSAndroid Build Coastguard Worker 			    r = memchr (r, '\0', q - r);
4151*7304104dSAndroid Build Coastguard Worker 			    if (r == NULL)
4152*7304104dSAndroid Build Coastguard Worker 			      break;
4153*7304104dSAndroid Build Coastguard Worker 			    ++r;
4154*7304104dSAndroid Build Coastguard Worker 			  }
4155*7304104dSAndroid Build Coastguard Worker 
4156*7304104dSAndroid Build Coastguard Worker 			const char *tag_name = NULL;
4157*7304104dSAndroid Build Coastguard Worker 			const char *value_name = NULL;
4158*7304104dSAndroid Build Coastguard Worker 			ebl_check_object_attribute (ebl, (const char *) name,
4159*7304104dSAndroid Build Coastguard Worker 						    tag, value,
4160*7304104dSAndroid Build Coastguard Worker 						    &tag_name, &value_name);
4161*7304104dSAndroid Build Coastguard Worker 
4162*7304104dSAndroid Build Coastguard Worker 			if (tag_name != NULL)
4163*7304104dSAndroid Build Coastguard Worker 			  {
4164*7304104dSAndroid Build Coastguard Worker 			    if (tag == 32)
4165*7304104dSAndroid Build Coastguard Worker 			      printf (_("      %s: %" PRId64 ", %s\n"),
4166*7304104dSAndroid Build Coastguard Worker 				      tag_name, value, string);
4167*7304104dSAndroid Build Coastguard Worker 			    else if (string == NULL && value_name == NULL)
4168*7304104dSAndroid Build Coastguard Worker 			      printf (_("      %s: %" PRId64 "\n"),
4169*7304104dSAndroid Build Coastguard Worker 				      tag_name, value);
4170*7304104dSAndroid Build Coastguard Worker 			    else
4171*7304104dSAndroid Build Coastguard Worker 			      printf (_("      %s: %s\n"),
4172*7304104dSAndroid Build Coastguard Worker 				      tag_name, string ?: value_name);
4173*7304104dSAndroid Build Coastguard Worker 			  }
4174*7304104dSAndroid Build Coastguard Worker 			else
4175*7304104dSAndroid Build Coastguard Worker 			  {
4176*7304104dSAndroid Build Coastguard Worker 			    /* For "gnu" vendor 32 "compatibility" has
4177*7304104dSAndroid Build Coastguard Worker 			       already been handled above.  */
4178*7304104dSAndroid Build Coastguard Worker 			    assert (tag != 32
4179*7304104dSAndroid Build Coastguard Worker 				    || strcmp ((const char *) name, "gnu"));
4180*7304104dSAndroid Build Coastguard Worker 			    if (string == NULL)
4181*7304104dSAndroid Build Coastguard Worker 			      printf (_("      %u: %" PRId64 "\n"),
4182*7304104dSAndroid Build Coastguard Worker 				      tag, value);
4183*7304104dSAndroid Build Coastguard Worker 			    else
4184*7304104dSAndroid Build Coastguard Worker 			      printf (_("      %u: %s\n"),
4185*7304104dSAndroid Build Coastguard Worker 				      tag, string);
4186*7304104dSAndroid Build Coastguard Worker 			  }
4187*7304104dSAndroid Build Coastguard Worker 		      }
4188*7304104dSAndroid Build Coastguard Worker 		  }
4189*7304104dSAndroid Build Coastguard Worker 	      }
4190*7304104dSAndroid Build Coastguard Worker 	}
4191*7304104dSAndroid Build Coastguard Worker     }
4192*7304104dSAndroid Build Coastguard Worker }
4193*7304104dSAndroid Build Coastguard Worker 
4194*7304104dSAndroid Build Coastguard Worker /* Returns either the (relocated) data from the Dwarf, or tries to get
4195*7304104dSAndroid Build Coastguard Worker    the "raw" (uncompressed) data from the Elf section. Produces a
4196*7304104dSAndroid Build Coastguard Worker    warning if the data cannot be found (or decompressed).  */
4197*7304104dSAndroid Build Coastguard Worker static Elf_Data *
get_debug_elf_data(Dwarf * dbg,Ebl * ebl,int idx,Elf_Scn * scn)4198*7304104dSAndroid Build Coastguard Worker get_debug_elf_data (Dwarf *dbg, Ebl *ebl, int idx, Elf_Scn *scn)
4199*7304104dSAndroid Build Coastguard Worker {
4200*7304104dSAndroid Build Coastguard Worker   /* We prefer to get the section data from the Dwarf because that
4201*7304104dSAndroid Build Coastguard Worker      might have been relocated already.  Note this is subtly wrong if
4202*7304104dSAndroid Build Coastguard Worker      there are multiple sections with the same .debug name.  */
4203*7304104dSAndroid Build Coastguard Worker   if (dbg->sectiondata[idx] != NULL)
4204*7304104dSAndroid Build Coastguard Worker     return dbg->sectiondata[idx];
4205*7304104dSAndroid Build Coastguard Worker 
4206*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
4207*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
4208*7304104dSAndroid Build Coastguard Worker   if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
4209*7304104dSAndroid Build Coastguard Worker     {
4210*7304104dSAndroid Build Coastguard Worker       if (elf_compress (scn, 0, 0) < 0)
4211*7304104dSAndroid Build Coastguard Worker 	{
4212*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, "%s [%zd] '%s'\n",
4213*7304104dSAndroid Build Coastguard Worker 		 _("Couldn't uncompress section"),
4214*7304104dSAndroid Build Coastguard Worker 		 elf_ndxscn (scn), section_name (ebl, shdr));
4215*7304104dSAndroid Build Coastguard Worker 	  return NULL;
4216*7304104dSAndroid Build Coastguard Worker 	}
4217*7304104dSAndroid Build Coastguard Worker     }
4218*7304104dSAndroid Build Coastguard Worker 
4219*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata (scn, NULL);
4220*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
4221*7304104dSAndroid Build Coastguard Worker     error (0, 0, "%s [%zd] '%s': %s\n",
4222*7304104dSAndroid Build Coastguard Worker 	   _("Couldn't get data from section"),
4223*7304104dSAndroid Build Coastguard Worker 	   elf_ndxscn (scn), section_name (ebl, shdr), elf_errmsg (-1));
4224*7304104dSAndroid Build Coastguard Worker 
4225*7304104dSAndroid Build Coastguard Worker   return elf_getdata (scn, NULL);
4226*7304104dSAndroid Build Coastguard Worker }
4227*7304104dSAndroid Build Coastguard Worker 
4228*7304104dSAndroid Build Coastguard Worker static void
print_dwarf_addr(Dwfl_Module * dwflmod,int address_size,Dwarf_Addr address,Dwarf_Addr raw)4229*7304104dSAndroid Build Coastguard Worker print_dwarf_addr (Dwfl_Module *dwflmod,
4230*7304104dSAndroid Build Coastguard Worker 		  int address_size, Dwarf_Addr address, Dwarf_Addr raw)
4231*7304104dSAndroid Build Coastguard Worker {
4232*7304104dSAndroid Build Coastguard Worker   /* See if there is a name we can give for this address.  */
4233*7304104dSAndroid Build Coastguard Worker   GElf_Sym sym;
4234*7304104dSAndroid Build Coastguard Worker   GElf_Off off = 0;
4235*7304104dSAndroid Build Coastguard Worker   const char *name = (print_address_names && ! print_unresolved_addresses)
4236*7304104dSAndroid Build Coastguard Worker     ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
4237*7304104dSAndroid Build Coastguard Worker     : NULL;
4238*7304104dSAndroid Build Coastguard Worker 
4239*7304104dSAndroid Build Coastguard Worker   const char *scn;
4240*7304104dSAndroid Build Coastguard Worker   if (print_unresolved_addresses)
4241*7304104dSAndroid Build Coastguard Worker     {
4242*7304104dSAndroid Build Coastguard Worker       address = raw;
4243*7304104dSAndroid Build Coastguard Worker       scn = NULL;
4244*7304104dSAndroid Build Coastguard Worker     }
4245*7304104dSAndroid Build Coastguard Worker   else
4246*7304104dSAndroid Build Coastguard Worker     {
4247*7304104dSAndroid Build Coastguard Worker       /* Relativize the address.  */
4248*7304104dSAndroid Build Coastguard Worker       int n = dwfl_module_relocations (dwflmod);
4249*7304104dSAndroid Build Coastguard Worker       int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
4250*7304104dSAndroid Build Coastguard Worker 
4251*7304104dSAndroid Build Coastguard Worker       /* In an ET_REL file there is a section name to refer to.  */
4252*7304104dSAndroid Build Coastguard Worker       scn = (i < 0 ? NULL
4253*7304104dSAndroid Build Coastguard Worker 	     : dwfl_module_relocation_info (dwflmod, i, NULL));
4254*7304104dSAndroid Build Coastguard Worker     }
4255*7304104dSAndroid Build Coastguard Worker 
4256*7304104dSAndroid Build Coastguard Worker   if ((name != NULL
4257*7304104dSAndroid Build Coastguard Worker        ? (off != 0
4258*7304104dSAndroid Build Coastguard Worker 	  ? (scn != NULL
4259*7304104dSAndroid Build Coastguard Worker 	     ? (address_size == 0
4260*7304104dSAndroid Build Coastguard Worker 		? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
4261*7304104dSAndroid Build Coastguard Worker 			  scn, address, name, off)
4262*7304104dSAndroid Build Coastguard Worker 		: printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
4263*7304104dSAndroid Build Coastguard Worker 			  scn, 2 + address_size * 2, address,
4264*7304104dSAndroid Build Coastguard Worker 			  name, off))
4265*7304104dSAndroid Build Coastguard Worker 	     : (address_size == 0
4266*7304104dSAndroid Build Coastguard Worker 		? printf ("%#" PRIx64 " <%s+%#" PRIx64 ">",
4267*7304104dSAndroid Build Coastguard Worker 			  address, name, off)
4268*7304104dSAndroid Build Coastguard Worker 		: printf ("%#0*" PRIx64 " <%s+%#" PRIx64 ">",
4269*7304104dSAndroid Build Coastguard Worker 			  2 + address_size * 2, address,
4270*7304104dSAndroid Build Coastguard Worker 			  name, off)))
4271*7304104dSAndroid Build Coastguard Worker 	  : (scn != NULL
4272*7304104dSAndroid Build Coastguard Worker 	     ? (address_size == 0
4273*7304104dSAndroid Build Coastguard Worker 		? printf ("%s+%#" PRIx64 " <%s>", scn, address, name)
4274*7304104dSAndroid Build Coastguard Worker 		: printf ("%s+%#0*" PRIx64 " <%s>",
4275*7304104dSAndroid Build Coastguard Worker 			   scn, 2 + address_size * 2, address, name))
4276*7304104dSAndroid Build Coastguard Worker 	     : (address_size == 0
4277*7304104dSAndroid Build Coastguard Worker 		? printf ("%#" PRIx64 " <%s>", address, name)
4278*7304104dSAndroid Build Coastguard Worker 		: printf ("%#0*" PRIx64 " <%s>",
4279*7304104dSAndroid Build Coastguard Worker 			  2 + address_size * 2, address, name))))
4280*7304104dSAndroid Build Coastguard Worker        : (scn != NULL
4281*7304104dSAndroid Build Coastguard Worker 	  ? (address_size == 0
4282*7304104dSAndroid Build Coastguard Worker 	     ? printf ("%s+%#" PRIx64, scn, address)
4283*7304104dSAndroid Build Coastguard Worker 	     : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
4284*7304104dSAndroid Build Coastguard Worker 	  : (address_size == 0
4285*7304104dSAndroid Build Coastguard Worker 	     ? printf ("%#" PRIx64, address)
4286*7304104dSAndroid Build Coastguard Worker 	     : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
4287*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("sprintf failure"));
4288*7304104dSAndroid Build Coastguard Worker }
4289*7304104dSAndroid Build Coastguard Worker 
4290*7304104dSAndroid Build Coastguard Worker 
4291*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_tag_string(unsigned int tag)4292*7304104dSAndroid Build Coastguard Worker dwarf_tag_string (unsigned int tag)
4293*7304104dSAndroid Build Coastguard Worker {
4294*7304104dSAndroid Build Coastguard Worker   switch (tag)
4295*7304104dSAndroid Build Coastguard Worker     {
4296*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
4297*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_TAG
4298*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_TAG
4299*7304104dSAndroid Build Coastguard Worker     default:
4300*7304104dSAndroid Build Coastguard Worker       return NULL;
4301*7304104dSAndroid Build Coastguard Worker     }
4302*7304104dSAndroid Build Coastguard Worker }
4303*7304104dSAndroid Build Coastguard Worker 
4304*7304104dSAndroid Build Coastguard Worker 
4305*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_attr_string(unsigned int attrnum)4306*7304104dSAndroid Build Coastguard Worker dwarf_attr_string (unsigned int attrnum)
4307*7304104dSAndroid Build Coastguard Worker {
4308*7304104dSAndroid Build Coastguard Worker   switch (attrnum)
4309*7304104dSAndroid Build Coastguard Worker     {
4310*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
4311*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_AT
4312*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_AT
4313*7304104dSAndroid Build Coastguard Worker     default:
4314*7304104dSAndroid Build Coastguard Worker       return NULL;
4315*7304104dSAndroid Build Coastguard Worker     }
4316*7304104dSAndroid Build Coastguard Worker }
4317*7304104dSAndroid Build Coastguard Worker 
4318*7304104dSAndroid Build Coastguard Worker 
4319*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_form_string(unsigned int form)4320*7304104dSAndroid Build Coastguard Worker dwarf_form_string (unsigned int form)
4321*7304104dSAndroid Build Coastguard Worker {
4322*7304104dSAndroid Build Coastguard Worker   switch (form)
4323*7304104dSAndroid Build Coastguard Worker     {
4324*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
4325*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_FORM
4326*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_FORM
4327*7304104dSAndroid Build Coastguard Worker     default:
4328*7304104dSAndroid Build Coastguard Worker       return NULL;
4329*7304104dSAndroid Build Coastguard Worker     }
4330*7304104dSAndroid Build Coastguard Worker }
4331*7304104dSAndroid Build Coastguard Worker 
4332*7304104dSAndroid Build Coastguard Worker 
4333*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_lang_string(unsigned int lang)4334*7304104dSAndroid Build Coastguard Worker dwarf_lang_string (unsigned int lang)
4335*7304104dSAndroid Build Coastguard Worker {
4336*7304104dSAndroid Build Coastguard Worker   switch (lang)
4337*7304104dSAndroid Build Coastguard Worker     {
4338*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
4339*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_LANG
4340*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_LANG
4341*7304104dSAndroid Build Coastguard Worker     default:
4342*7304104dSAndroid Build Coastguard Worker       return NULL;
4343*7304104dSAndroid Build Coastguard Worker     }
4344*7304104dSAndroid Build Coastguard Worker }
4345*7304104dSAndroid Build Coastguard Worker 
4346*7304104dSAndroid Build Coastguard Worker 
4347*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_inline_string(unsigned int code)4348*7304104dSAndroid Build Coastguard Worker dwarf_inline_string (unsigned int code)
4349*7304104dSAndroid Build Coastguard Worker {
4350*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4351*7304104dSAndroid Build Coastguard Worker     {
4352*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
4353*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_INL
4354*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_INL
4355*7304104dSAndroid Build Coastguard Worker     };
4356*7304104dSAndroid Build Coastguard Worker 
4357*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4358*7304104dSAndroid Build Coastguard Worker     return known[code];
4359*7304104dSAndroid Build Coastguard Worker 
4360*7304104dSAndroid Build Coastguard Worker   return NULL;
4361*7304104dSAndroid Build Coastguard Worker }
4362*7304104dSAndroid Build Coastguard Worker 
4363*7304104dSAndroid Build Coastguard Worker 
4364*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_encoding_string(unsigned int code)4365*7304104dSAndroid Build Coastguard Worker dwarf_encoding_string (unsigned int code)
4366*7304104dSAndroid Build Coastguard Worker {
4367*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4368*7304104dSAndroid Build Coastguard Worker     {
4369*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
4370*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_ATE
4371*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_ATE
4372*7304104dSAndroid Build Coastguard Worker     };
4373*7304104dSAndroid Build Coastguard Worker 
4374*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4375*7304104dSAndroid Build Coastguard Worker     return known[code];
4376*7304104dSAndroid Build Coastguard Worker 
4377*7304104dSAndroid Build Coastguard Worker   return NULL;
4378*7304104dSAndroid Build Coastguard Worker }
4379*7304104dSAndroid Build Coastguard Worker 
4380*7304104dSAndroid Build Coastguard Worker 
4381*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_access_string(unsigned int code)4382*7304104dSAndroid Build Coastguard Worker dwarf_access_string (unsigned int code)
4383*7304104dSAndroid Build Coastguard Worker {
4384*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4385*7304104dSAndroid Build Coastguard Worker     {
4386*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
4387*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_ACCESS
4388*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_ACCESS
4389*7304104dSAndroid Build Coastguard Worker     };
4390*7304104dSAndroid Build Coastguard Worker 
4391*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4392*7304104dSAndroid Build Coastguard Worker     return known[code];
4393*7304104dSAndroid Build Coastguard Worker 
4394*7304104dSAndroid Build Coastguard Worker   return NULL;
4395*7304104dSAndroid Build Coastguard Worker }
4396*7304104dSAndroid Build Coastguard Worker 
4397*7304104dSAndroid Build Coastguard Worker 
4398*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_defaulted_string(unsigned int code)4399*7304104dSAndroid Build Coastguard Worker dwarf_defaulted_string (unsigned int code)
4400*7304104dSAndroid Build Coastguard Worker {
4401*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4402*7304104dSAndroid Build Coastguard Worker     {
4403*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
4404*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_DEFAULTED
4405*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_DEFAULTED
4406*7304104dSAndroid Build Coastguard Worker     };
4407*7304104dSAndroid Build Coastguard Worker 
4408*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4409*7304104dSAndroid Build Coastguard Worker     return known[code];
4410*7304104dSAndroid Build Coastguard Worker 
4411*7304104dSAndroid Build Coastguard Worker   return NULL;
4412*7304104dSAndroid Build Coastguard Worker }
4413*7304104dSAndroid Build Coastguard Worker 
4414*7304104dSAndroid Build Coastguard Worker 
4415*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_visibility_string(unsigned int code)4416*7304104dSAndroid Build Coastguard Worker dwarf_visibility_string (unsigned int code)
4417*7304104dSAndroid Build Coastguard Worker {
4418*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4419*7304104dSAndroid Build Coastguard Worker     {
4420*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
4421*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_VIS
4422*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_VIS
4423*7304104dSAndroid Build Coastguard Worker     };
4424*7304104dSAndroid Build Coastguard Worker 
4425*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4426*7304104dSAndroid Build Coastguard Worker     return known[code];
4427*7304104dSAndroid Build Coastguard Worker 
4428*7304104dSAndroid Build Coastguard Worker   return NULL;
4429*7304104dSAndroid Build Coastguard Worker }
4430*7304104dSAndroid Build Coastguard Worker 
4431*7304104dSAndroid Build Coastguard Worker 
4432*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_virtuality_string(unsigned int code)4433*7304104dSAndroid Build Coastguard Worker dwarf_virtuality_string (unsigned int code)
4434*7304104dSAndroid Build Coastguard Worker {
4435*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4436*7304104dSAndroid Build Coastguard Worker     {
4437*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
4438*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_VIRTUALITY
4439*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_VIRTUALITY
4440*7304104dSAndroid Build Coastguard Worker     };
4441*7304104dSAndroid Build Coastguard Worker 
4442*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4443*7304104dSAndroid Build Coastguard Worker     return known[code];
4444*7304104dSAndroid Build Coastguard Worker 
4445*7304104dSAndroid Build Coastguard Worker   return NULL;
4446*7304104dSAndroid Build Coastguard Worker }
4447*7304104dSAndroid Build Coastguard Worker 
4448*7304104dSAndroid Build Coastguard Worker 
4449*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_identifier_case_string(unsigned int code)4450*7304104dSAndroid Build Coastguard Worker dwarf_identifier_case_string (unsigned int code)
4451*7304104dSAndroid Build Coastguard Worker {
4452*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4453*7304104dSAndroid Build Coastguard Worker     {
4454*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
4455*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_ID
4456*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_ID
4457*7304104dSAndroid Build Coastguard Worker     };
4458*7304104dSAndroid Build Coastguard Worker 
4459*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4460*7304104dSAndroid Build Coastguard Worker     return known[code];
4461*7304104dSAndroid Build Coastguard Worker 
4462*7304104dSAndroid Build Coastguard Worker   return NULL;
4463*7304104dSAndroid Build Coastguard Worker }
4464*7304104dSAndroid Build Coastguard Worker 
4465*7304104dSAndroid Build Coastguard Worker 
4466*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_calling_convention_string(unsigned int code)4467*7304104dSAndroid Build Coastguard Worker dwarf_calling_convention_string (unsigned int code)
4468*7304104dSAndroid Build Coastguard Worker {
4469*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4470*7304104dSAndroid Build Coastguard Worker     {
4471*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
4472*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_CC
4473*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_CC
4474*7304104dSAndroid Build Coastguard Worker     };
4475*7304104dSAndroid Build Coastguard Worker 
4476*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4477*7304104dSAndroid Build Coastguard Worker     return known[code];
4478*7304104dSAndroid Build Coastguard Worker 
4479*7304104dSAndroid Build Coastguard Worker   return NULL;
4480*7304104dSAndroid Build Coastguard Worker }
4481*7304104dSAndroid Build Coastguard Worker 
4482*7304104dSAndroid Build Coastguard Worker 
4483*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_ordering_string(unsigned int code)4484*7304104dSAndroid Build Coastguard Worker dwarf_ordering_string (unsigned int code)
4485*7304104dSAndroid Build Coastguard Worker {
4486*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4487*7304104dSAndroid Build Coastguard Worker     {
4488*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
4489*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_ORD
4490*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_ORD
4491*7304104dSAndroid Build Coastguard Worker     };
4492*7304104dSAndroid Build Coastguard Worker 
4493*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4494*7304104dSAndroid Build Coastguard Worker     return known[code];
4495*7304104dSAndroid Build Coastguard Worker 
4496*7304104dSAndroid Build Coastguard Worker   return NULL;
4497*7304104dSAndroid Build Coastguard Worker }
4498*7304104dSAndroid Build Coastguard Worker 
4499*7304104dSAndroid Build Coastguard Worker 
4500*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_discr_list_string(unsigned int code)4501*7304104dSAndroid Build Coastguard Worker dwarf_discr_list_string (unsigned int code)
4502*7304104dSAndroid Build Coastguard Worker {
4503*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4504*7304104dSAndroid Build Coastguard Worker     {
4505*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
4506*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_DSC
4507*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_DSC
4508*7304104dSAndroid Build Coastguard Worker     };
4509*7304104dSAndroid Build Coastguard Worker 
4510*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4511*7304104dSAndroid Build Coastguard Worker     return known[code];
4512*7304104dSAndroid Build Coastguard Worker 
4513*7304104dSAndroid Build Coastguard Worker   return NULL;
4514*7304104dSAndroid Build Coastguard Worker }
4515*7304104dSAndroid Build Coastguard Worker 
4516*7304104dSAndroid Build Coastguard Worker 
4517*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_locexpr_opcode_string(unsigned int code)4518*7304104dSAndroid Build Coastguard Worker dwarf_locexpr_opcode_string (unsigned int code)
4519*7304104dSAndroid Build Coastguard Worker {
4520*7304104dSAndroid Build Coastguard Worker   static const char *const known[] =
4521*7304104dSAndroid Build Coastguard Worker     {
4522*7304104dSAndroid Build Coastguard Worker       /* Normally we can't afford building huge table of 64K entries,
4523*7304104dSAndroid Build Coastguard Worker 	 most of them zero, just because there are a couple defined
4524*7304104dSAndroid Build Coastguard Worker 	 values at the far end.  In case of opcodes, it's OK.  */
4525*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
4526*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_OP
4527*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_OP
4528*7304104dSAndroid Build Coastguard Worker     };
4529*7304104dSAndroid Build Coastguard Worker 
4530*7304104dSAndroid Build Coastguard Worker   if (likely (code < sizeof (known) / sizeof (known[0])))
4531*7304104dSAndroid Build Coastguard Worker     return known[code];
4532*7304104dSAndroid Build Coastguard Worker 
4533*7304104dSAndroid Build Coastguard Worker   return NULL;
4534*7304104dSAndroid Build Coastguard Worker }
4535*7304104dSAndroid Build Coastguard Worker 
4536*7304104dSAndroid Build Coastguard Worker 
4537*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_unit_string(unsigned int type)4538*7304104dSAndroid Build Coastguard Worker dwarf_unit_string (unsigned int type)
4539*7304104dSAndroid Build Coastguard Worker {
4540*7304104dSAndroid Build Coastguard Worker   switch (type)
4541*7304104dSAndroid Build Coastguard Worker     {
4542*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_UT(NAME, CODE) case CODE: return #NAME;
4543*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_UT
4544*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_UT
4545*7304104dSAndroid Build Coastguard Worker     default:
4546*7304104dSAndroid Build Coastguard Worker       return NULL;
4547*7304104dSAndroid Build Coastguard Worker     }
4548*7304104dSAndroid Build Coastguard Worker }
4549*7304104dSAndroid Build Coastguard Worker 
4550*7304104dSAndroid Build Coastguard Worker 
4551*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_range_list_encoding_string(unsigned int kind)4552*7304104dSAndroid Build Coastguard Worker dwarf_range_list_encoding_string (unsigned int kind)
4553*7304104dSAndroid Build Coastguard Worker {
4554*7304104dSAndroid Build Coastguard Worker   switch (kind)
4555*7304104dSAndroid Build Coastguard Worker     {
4556*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_RLE(NAME, CODE) case CODE: return #NAME;
4557*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_RLE
4558*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_RLE
4559*7304104dSAndroid Build Coastguard Worker     default:
4560*7304104dSAndroid Build Coastguard Worker       return NULL;
4561*7304104dSAndroid Build Coastguard Worker     }
4562*7304104dSAndroid Build Coastguard Worker }
4563*7304104dSAndroid Build Coastguard Worker 
4564*7304104dSAndroid Build Coastguard Worker 
4565*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_loc_list_encoding_string(unsigned int kind)4566*7304104dSAndroid Build Coastguard Worker dwarf_loc_list_encoding_string (unsigned int kind)
4567*7304104dSAndroid Build Coastguard Worker {
4568*7304104dSAndroid Build Coastguard Worker   switch (kind)
4569*7304104dSAndroid Build Coastguard Worker     {
4570*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_LLE(NAME, CODE) case CODE: return #NAME;
4571*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_LLE
4572*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_LLE
4573*7304104dSAndroid Build Coastguard Worker     /* DW_LLE_GNU_view_pair is special/incompatible with default codes.  */
4574*7304104dSAndroid Build Coastguard Worker     case DW_LLE_GNU_view_pair: return "GNU_view_pair";
4575*7304104dSAndroid Build Coastguard Worker     default:
4576*7304104dSAndroid Build Coastguard Worker       return NULL;
4577*7304104dSAndroid Build Coastguard Worker     }
4578*7304104dSAndroid Build Coastguard Worker }
4579*7304104dSAndroid Build Coastguard Worker 
4580*7304104dSAndroid Build Coastguard Worker 
4581*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_line_content_description_string(unsigned int kind)4582*7304104dSAndroid Build Coastguard Worker dwarf_line_content_description_string (unsigned int kind)
4583*7304104dSAndroid Build Coastguard Worker {
4584*7304104dSAndroid Build Coastguard Worker   switch (kind)
4585*7304104dSAndroid Build Coastguard Worker     {
4586*7304104dSAndroid Build Coastguard Worker #define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME;
4587*7304104dSAndroid Build Coastguard Worker       DWARF_ALL_KNOWN_DW_LNCT
4588*7304104dSAndroid Build Coastguard Worker #undef DWARF_ONE_KNOWN_DW_LNCT
4589*7304104dSAndroid Build Coastguard Worker     default:
4590*7304104dSAndroid Build Coastguard Worker       return NULL;
4591*7304104dSAndroid Build Coastguard Worker     }
4592*7304104dSAndroid Build Coastguard Worker }
4593*7304104dSAndroid Build Coastguard Worker 
4594*7304104dSAndroid Build Coastguard Worker 
4595*7304104dSAndroid Build Coastguard Worker /* Used by all dwarf_foo_name functions.  */
4596*7304104dSAndroid Build Coastguard Worker static const char *
string_or_unknown(const char * known,unsigned int code,unsigned int lo_user,unsigned int hi_user,bool print_unknown_num)4597*7304104dSAndroid Build Coastguard Worker string_or_unknown (const char *known, unsigned int code,
4598*7304104dSAndroid Build Coastguard Worker                    unsigned int lo_user, unsigned int hi_user,
4599*7304104dSAndroid Build Coastguard Worker 		   bool print_unknown_num)
4600*7304104dSAndroid Build Coastguard Worker {
4601*7304104dSAndroid Build Coastguard Worker   static char unknown_buf[20];
4602*7304104dSAndroid Build Coastguard Worker 
4603*7304104dSAndroid Build Coastguard Worker   if (likely (known != NULL))
4604*7304104dSAndroid Build Coastguard Worker     return known;
4605*7304104dSAndroid Build Coastguard Worker 
4606*7304104dSAndroid Build Coastguard Worker   if (lo_user != 0 && code >= lo_user && code <= hi_user)
4607*7304104dSAndroid Build Coastguard Worker     {
4608*7304104dSAndroid Build Coastguard Worker       snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
4609*7304104dSAndroid Build Coastguard Worker 		code - lo_user);
4610*7304104dSAndroid Build Coastguard Worker       return unknown_buf;
4611*7304104dSAndroid Build Coastguard Worker     }
4612*7304104dSAndroid Build Coastguard Worker 
4613*7304104dSAndroid Build Coastguard Worker   if (print_unknown_num)
4614*7304104dSAndroid Build Coastguard Worker     {
4615*7304104dSAndroid Build Coastguard Worker       snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
4616*7304104dSAndroid Build Coastguard Worker       return unknown_buf;
4617*7304104dSAndroid Build Coastguard Worker     }
4618*7304104dSAndroid Build Coastguard Worker 
4619*7304104dSAndroid Build Coastguard Worker   return "???";
4620*7304104dSAndroid Build Coastguard Worker }
4621*7304104dSAndroid Build Coastguard Worker 
4622*7304104dSAndroid Build Coastguard Worker 
4623*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_tag_name(unsigned int tag)4624*7304104dSAndroid Build Coastguard Worker dwarf_tag_name (unsigned int tag)
4625*7304104dSAndroid Build Coastguard Worker {
4626*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_tag_string (tag);
4627*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
4628*7304104dSAndroid Build Coastguard Worker }
4629*7304104dSAndroid Build Coastguard Worker 
4630*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_attr_name(unsigned int attr)4631*7304104dSAndroid Build Coastguard Worker dwarf_attr_name (unsigned int attr)
4632*7304104dSAndroid Build Coastguard Worker {
4633*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_attr_string (attr);
4634*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
4635*7304104dSAndroid Build Coastguard Worker }
4636*7304104dSAndroid Build Coastguard Worker 
4637*7304104dSAndroid Build Coastguard Worker 
4638*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_form_name(unsigned int form)4639*7304104dSAndroid Build Coastguard Worker dwarf_form_name (unsigned int form)
4640*7304104dSAndroid Build Coastguard Worker {
4641*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_form_string (form);
4642*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, form, 0, 0, true);
4643*7304104dSAndroid Build Coastguard Worker }
4644*7304104dSAndroid Build Coastguard Worker 
4645*7304104dSAndroid Build Coastguard Worker 
4646*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_lang_name(unsigned int lang)4647*7304104dSAndroid Build Coastguard Worker dwarf_lang_name (unsigned int lang)
4648*7304104dSAndroid Build Coastguard Worker {
4649*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_lang_string (lang);
4650*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
4651*7304104dSAndroid Build Coastguard Worker }
4652*7304104dSAndroid Build Coastguard Worker 
4653*7304104dSAndroid Build Coastguard Worker 
4654*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_inline_name(unsigned int code)4655*7304104dSAndroid Build Coastguard Worker dwarf_inline_name (unsigned int code)
4656*7304104dSAndroid Build Coastguard Worker {
4657*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_inline_string (code);
4658*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4659*7304104dSAndroid Build Coastguard Worker }
4660*7304104dSAndroid Build Coastguard Worker 
4661*7304104dSAndroid Build Coastguard Worker 
4662*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_encoding_name(unsigned int code)4663*7304104dSAndroid Build Coastguard Worker dwarf_encoding_name (unsigned int code)
4664*7304104dSAndroid Build Coastguard Worker {
4665*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_encoding_string (code);
4666*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
4667*7304104dSAndroid Build Coastguard Worker }
4668*7304104dSAndroid Build Coastguard Worker 
4669*7304104dSAndroid Build Coastguard Worker 
4670*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_access_name(unsigned int code)4671*7304104dSAndroid Build Coastguard Worker dwarf_access_name (unsigned int code)
4672*7304104dSAndroid Build Coastguard Worker {
4673*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_access_string (code);
4674*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4675*7304104dSAndroid Build Coastguard Worker }
4676*7304104dSAndroid Build Coastguard Worker 
4677*7304104dSAndroid Build Coastguard Worker 
4678*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_defaulted_name(unsigned int code)4679*7304104dSAndroid Build Coastguard Worker dwarf_defaulted_name (unsigned int code)
4680*7304104dSAndroid Build Coastguard Worker {
4681*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_defaulted_string (code);
4682*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4683*7304104dSAndroid Build Coastguard Worker }
4684*7304104dSAndroid Build Coastguard Worker 
4685*7304104dSAndroid Build Coastguard Worker 
4686*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_visibility_name(unsigned int code)4687*7304104dSAndroid Build Coastguard Worker dwarf_visibility_name (unsigned int code)
4688*7304104dSAndroid Build Coastguard Worker {
4689*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_visibility_string (code);
4690*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4691*7304104dSAndroid Build Coastguard Worker }
4692*7304104dSAndroid Build Coastguard Worker 
4693*7304104dSAndroid Build Coastguard Worker 
4694*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_virtuality_name(unsigned int code)4695*7304104dSAndroid Build Coastguard Worker dwarf_virtuality_name (unsigned int code)
4696*7304104dSAndroid Build Coastguard Worker {
4697*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_virtuality_string (code);
4698*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4699*7304104dSAndroid Build Coastguard Worker }
4700*7304104dSAndroid Build Coastguard Worker 
4701*7304104dSAndroid Build Coastguard Worker 
4702*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_identifier_case_name(unsigned int code)4703*7304104dSAndroid Build Coastguard Worker dwarf_identifier_case_name (unsigned int code)
4704*7304104dSAndroid Build Coastguard Worker {
4705*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_identifier_case_string (code);
4706*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4707*7304104dSAndroid Build Coastguard Worker }
4708*7304104dSAndroid Build Coastguard Worker 
4709*7304104dSAndroid Build Coastguard Worker 
4710*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_calling_convention_name(unsigned int code)4711*7304104dSAndroid Build Coastguard Worker dwarf_calling_convention_name (unsigned int code)
4712*7304104dSAndroid Build Coastguard Worker {
4713*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_calling_convention_string (code);
4714*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
4715*7304104dSAndroid Build Coastguard Worker }
4716*7304104dSAndroid Build Coastguard Worker 
4717*7304104dSAndroid Build Coastguard Worker 
4718*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_ordering_name(unsigned int code)4719*7304104dSAndroid Build Coastguard Worker dwarf_ordering_name (unsigned int code)
4720*7304104dSAndroid Build Coastguard Worker {
4721*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_ordering_string (code);
4722*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4723*7304104dSAndroid Build Coastguard Worker }
4724*7304104dSAndroid Build Coastguard Worker 
4725*7304104dSAndroid Build Coastguard Worker 
4726*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_discr_list_name(unsigned int code)4727*7304104dSAndroid Build Coastguard Worker dwarf_discr_list_name (unsigned int code)
4728*7304104dSAndroid Build Coastguard Worker {
4729*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_discr_list_string (code);
4730*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, code, 0, 0, false);
4731*7304104dSAndroid Build Coastguard Worker }
4732*7304104dSAndroid Build Coastguard Worker 
4733*7304104dSAndroid Build Coastguard Worker 
4734*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_unit_name(unsigned int type)4735*7304104dSAndroid Build Coastguard Worker dwarf_unit_name (unsigned int type)
4736*7304104dSAndroid Build Coastguard Worker {
4737*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_unit_string (type);
4738*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, type, DW_UT_lo_user, DW_UT_hi_user, true);
4739*7304104dSAndroid Build Coastguard Worker }
4740*7304104dSAndroid Build Coastguard Worker 
4741*7304104dSAndroid Build Coastguard Worker 
4742*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_range_list_encoding_name(unsigned int kind)4743*7304104dSAndroid Build Coastguard Worker dwarf_range_list_encoding_name (unsigned int kind)
4744*7304104dSAndroid Build Coastguard Worker {
4745*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_range_list_encoding_string (kind);
4746*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, kind, 0, 0, false);
4747*7304104dSAndroid Build Coastguard Worker }
4748*7304104dSAndroid Build Coastguard Worker 
4749*7304104dSAndroid Build Coastguard Worker 
4750*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_loc_list_encoding_name(unsigned int kind)4751*7304104dSAndroid Build Coastguard Worker dwarf_loc_list_encoding_name (unsigned int kind)
4752*7304104dSAndroid Build Coastguard Worker {
4753*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_loc_list_encoding_string (kind);
4754*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, kind, 0, 0, false);
4755*7304104dSAndroid Build Coastguard Worker }
4756*7304104dSAndroid Build Coastguard Worker 
4757*7304104dSAndroid Build Coastguard Worker 
4758*7304104dSAndroid Build Coastguard Worker static const char *
dwarf_line_content_description_name(unsigned int kind)4759*7304104dSAndroid Build Coastguard Worker dwarf_line_content_description_name (unsigned int kind)
4760*7304104dSAndroid Build Coastguard Worker {
4761*7304104dSAndroid Build Coastguard Worker   const char *ret = dwarf_line_content_description_string (kind);
4762*7304104dSAndroid Build Coastguard Worker   return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user,
4763*7304104dSAndroid Build Coastguard Worker 			    false);
4764*7304104dSAndroid Build Coastguard Worker }
4765*7304104dSAndroid Build Coastguard Worker 
4766*7304104dSAndroid Build Coastguard Worker 
4767*7304104dSAndroid Build Coastguard Worker static void
print_block(size_t n,const void * block)4768*7304104dSAndroid Build Coastguard Worker print_block (size_t n, const void *block)
4769*7304104dSAndroid Build Coastguard Worker {
4770*7304104dSAndroid Build Coastguard Worker   if (n == 0)
4771*7304104dSAndroid Build Coastguard Worker     puts (_("empty block"));
4772*7304104dSAndroid Build Coastguard Worker   else
4773*7304104dSAndroid Build Coastguard Worker     {
4774*7304104dSAndroid Build Coastguard Worker       printf (_("%zu byte block:"), n);
4775*7304104dSAndroid Build Coastguard Worker       const unsigned char *data = block;
4776*7304104dSAndroid Build Coastguard Worker       do
4777*7304104dSAndroid Build Coastguard Worker 	printf (" %02x", *data++);
4778*7304104dSAndroid Build Coastguard Worker       while (--n > 0);
4779*7304104dSAndroid Build Coastguard Worker       putchar ('\n');
4780*7304104dSAndroid Build Coastguard Worker     }
4781*7304104dSAndroid Build Coastguard Worker }
4782*7304104dSAndroid Build Coastguard Worker 
4783*7304104dSAndroid Build Coastguard Worker static void
print_bytes(size_t n,const unsigned char * bytes)4784*7304104dSAndroid Build Coastguard Worker print_bytes (size_t n, const unsigned char *bytes)
4785*7304104dSAndroid Build Coastguard Worker {
4786*7304104dSAndroid Build Coastguard Worker   while (n-- > 0)
4787*7304104dSAndroid Build Coastguard Worker     {
4788*7304104dSAndroid Build Coastguard Worker       printf ("%02x", *bytes++);
4789*7304104dSAndroid Build Coastguard Worker       if (n > 0)
4790*7304104dSAndroid Build Coastguard Worker 	printf (" ");
4791*7304104dSAndroid Build Coastguard Worker     }
4792*7304104dSAndroid Build Coastguard Worker }
4793*7304104dSAndroid Build Coastguard Worker 
4794*7304104dSAndroid Build Coastguard Worker static int
get_indexed_addr(Dwarf_CU * cu,Dwarf_Word idx,Dwarf_Addr * addr)4795*7304104dSAndroid Build Coastguard Worker get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
4796*7304104dSAndroid Build Coastguard Worker {
4797*7304104dSAndroid Build Coastguard Worker   if (cu == NULL)
4798*7304104dSAndroid Build Coastguard Worker     return -1;
4799*7304104dSAndroid Build Coastguard Worker 
4800*7304104dSAndroid Build Coastguard Worker   Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
4801*7304104dSAndroid Build Coastguard Worker   if (debug_addr == NULL)
4802*7304104dSAndroid Build Coastguard Worker     return -1;
4803*7304104dSAndroid Build Coastguard Worker 
4804*7304104dSAndroid Build Coastguard Worker   Dwarf_Off base = __libdw_cu_addr_base (cu);
4805*7304104dSAndroid Build Coastguard Worker   Dwarf_Word off = idx * cu->address_size;
4806*7304104dSAndroid Build Coastguard Worker   if (base > debug_addr->d_size
4807*7304104dSAndroid Build Coastguard Worker       || off > debug_addr->d_size - base
4808*7304104dSAndroid Build Coastguard Worker       || cu->address_size > debug_addr->d_size - base - off)
4809*7304104dSAndroid Build Coastguard Worker     return -1;
4810*7304104dSAndroid Build Coastguard Worker 
4811*7304104dSAndroid Build Coastguard Worker   const unsigned char *addrp = debug_addr->d_buf + base + off;
4812*7304104dSAndroid Build Coastguard Worker   if (cu->address_size == 4)
4813*7304104dSAndroid Build Coastguard Worker     *addr = read_4ubyte_unaligned (cu->dbg, addrp);
4814*7304104dSAndroid Build Coastguard Worker   else
4815*7304104dSAndroid Build Coastguard Worker     *addr = read_8ubyte_unaligned (cu->dbg, addrp);
4816*7304104dSAndroid Build Coastguard Worker 
4817*7304104dSAndroid Build Coastguard Worker   return 0;
4818*7304104dSAndroid Build Coastguard Worker }
4819*7304104dSAndroid Build Coastguard Worker 
4820*7304104dSAndroid Build Coastguard Worker static void
print_ops(Dwfl_Module * dwflmod,Dwarf * dbg,int indent,int indentrest,unsigned int vers,unsigned int addrsize,unsigned int offset_size,struct Dwarf_CU * cu,Dwarf_Word len,const unsigned char * data)4821*7304104dSAndroid Build Coastguard Worker print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
4822*7304104dSAndroid Build Coastguard Worker 	   unsigned int vers, unsigned int addrsize, unsigned int offset_size,
4823*7304104dSAndroid Build Coastguard Worker 	   struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
4824*7304104dSAndroid Build Coastguard Worker {
4825*7304104dSAndroid Build Coastguard Worker   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
4826*7304104dSAndroid Build Coastguard Worker 
4827*7304104dSAndroid Build Coastguard Worker   if (len == 0)
4828*7304104dSAndroid Build Coastguard Worker     {
4829*7304104dSAndroid Build Coastguard Worker       printf ("%*s(empty)\n", indent, "");
4830*7304104dSAndroid Build Coastguard Worker       return;
4831*7304104dSAndroid Build Coastguard Worker     }
4832*7304104dSAndroid Build Coastguard Worker 
4833*7304104dSAndroid Build Coastguard Worker #define NEED(n)		if (len < (Dwarf_Word) (n)) goto invalid
4834*7304104dSAndroid Build Coastguard Worker #define CONSUME(n)	NEED (n); else len -= (n)
4835*7304104dSAndroid Build Coastguard Worker 
4836*7304104dSAndroid Build Coastguard Worker   Dwarf_Word offset = 0;
4837*7304104dSAndroid Build Coastguard Worker   while (len-- > 0)
4838*7304104dSAndroid Build Coastguard Worker     {
4839*7304104dSAndroid Build Coastguard Worker       uint_fast8_t op = *data++;
4840*7304104dSAndroid Build Coastguard Worker 
4841*7304104dSAndroid Build Coastguard Worker       const char *op_name = dwarf_locexpr_opcode_string (op);
4842*7304104dSAndroid Build Coastguard Worker       if (unlikely (op_name == NULL))
4843*7304104dSAndroid Build Coastguard Worker 	{
4844*7304104dSAndroid Build Coastguard Worker 	  static char buf[20];
4845*7304104dSAndroid Build Coastguard Worker 	  if (op >= DW_OP_lo_user)
4846*7304104dSAndroid Build Coastguard Worker 	    snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
4847*7304104dSAndroid Build Coastguard Worker 	  else
4848*7304104dSAndroid Build Coastguard Worker 	    snprintf (buf, sizeof buf, "??? (%#x)", op);
4849*7304104dSAndroid Build Coastguard Worker 	  op_name = buf;
4850*7304104dSAndroid Build Coastguard Worker 	}
4851*7304104dSAndroid Build Coastguard Worker 
4852*7304104dSAndroid Build Coastguard Worker       switch (op)
4853*7304104dSAndroid Build Coastguard Worker 	{
4854*7304104dSAndroid Build Coastguard Worker 	case DW_OP_addr:;
4855*7304104dSAndroid Build Coastguard Worker 	  /* Address operand.  */
4856*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word addr;
4857*7304104dSAndroid Build Coastguard Worker 	  NEED (addrsize);
4858*7304104dSAndroid Build Coastguard Worker 	  if (addrsize == 4)
4859*7304104dSAndroid Build Coastguard Worker 	    addr = read_4ubyte_unaligned (dbg, data);
4860*7304104dSAndroid Build Coastguard Worker 	  else if (addrsize == 8)
4861*7304104dSAndroid Build Coastguard Worker 	    addr = read_8ubyte_unaligned (dbg, data);
4862*7304104dSAndroid Build Coastguard Worker 	  else
4863*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
4864*7304104dSAndroid Build Coastguard Worker 	  data += addrsize;
4865*7304104dSAndroid Build Coastguard Worker 	  CONSUME (addrsize);
4866*7304104dSAndroid Build Coastguard Worker 
4867*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s ",
4868*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name);
4869*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, 0, addr, addr);
4870*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
4871*7304104dSAndroid Build Coastguard Worker 
4872*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + addrsize;
4873*7304104dSAndroid Build Coastguard Worker 	  break;
4874*7304104dSAndroid Build Coastguard Worker 
4875*7304104dSAndroid Build Coastguard Worker 	case DW_OP_call_ref:
4876*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_variable_value:
4877*7304104dSAndroid Build Coastguard Worker 	  /* Offset operand.  */
4878*7304104dSAndroid Build Coastguard Worker 	  if (ref_size != 4 && ref_size != 8)
4879*7304104dSAndroid Build Coastguard Worker 	    goto invalid; /* Cannot be used in CFA.  */
4880*7304104dSAndroid Build Coastguard Worker 	  NEED (ref_size);
4881*7304104dSAndroid Build Coastguard Worker 	  if (ref_size == 4)
4882*7304104dSAndroid Build Coastguard Worker 	    addr = read_4ubyte_unaligned (dbg, data);
4883*7304104dSAndroid Build Coastguard Worker 	  else
4884*7304104dSAndroid Build Coastguard Worker 	    addr = read_8ubyte_unaligned (dbg, data);
4885*7304104dSAndroid Build Coastguard Worker 	  data += ref_size;
4886*7304104dSAndroid Build Coastguard Worker 	  CONSUME (ref_size);
4887*7304104dSAndroid Build Coastguard Worker 	  /* addr is a DIE offset, so format it as one.  */
4888*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
4889*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4890*7304104dSAndroid Build Coastguard Worker 		  op_name, (uintmax_t) addr);
4891*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + ref_size;
4892*7304104dSAndroid Build Coastguard Worker 	  break;
4893*7304104dSAndroid Build Coastguard Worker 
4894*7304104dSAndroid Build Coastguard Worker 	case DW_OP_deref_size:
4895*7304104dSAndroid Build Coastguard Worker 	case DW_OP_xderef_size:
4896*7304104dSAndroid Build Coastguard Worker 	case DW_OP_pick:
4897*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const1u:
4898*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4899*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
4900*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
4901*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4902*7304104dSAndroid Build Coastguard Worker 		  op_name, *((uint8_t *) data));
4903*7304104dSAndroid Build Coastguard Worker 	  ++data;
4904*7304104dSAndroid Build Coastguard Worker 	  --len;
4905*7304104dSAndroid Build Coastguard Worker 	  offset += 2;
4906*7304104dSAndroid Build Coastguard Worker 	  break;
4907*7304104dSAndroid Build Coastguard Worker 
4908*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const2u:
4909*7304104dSAndroid Build Coastguard Worker 	  NEED (2);
4910*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4911*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
4912*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4913*7304104dSAndroid Build Coastguard Worker 		  op_name, read_2ubyte_unaligned (dbg, data));
4914*7304104dSAndroid Build Coastguard Worker 	  CONSUME (2);
4915*7304104dSAndroid Build Coastguard Worker 	  data += 2;
4916*7304104dSAndroid Build Coastguard Worker 	  offset += 3;
4917*7304104dSAndroid Build Coastguard Worker 	  break;
4918*7304104dSAndroid Build Coastguard Worker 
4919*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const4u:
4920*7304104dSAndroid Build Coastguard Worker 	  NEED (4);
4921*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4922*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
4923*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4924*7304104dSAndroid Build Coastguard Worker 		  op_name, read_4ubyte_unaligned (dbg, data));
4925*7304104dSAndroid Build Coastguard Worker 	  CONSUME (4);
4926*7304104dSAndroid Build Coastguard Worker 	  data += 4;
4927*7304104dSAndroid Build Coastguard Worker 	  offset += 5;
4928*7304104dSAndroid Build Coastguard Worker 	  break;
4929*7304104dSAndroid Build Coastguard Worker 
4930*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const8u:
4931*7304104dSAndroid Build Coastguard Worker 	  NEED (8);
4932*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4933*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
4934*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4935*7304104dSAndroid Build Coastguard Worker 		  op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
4936*7304104dSAndroid Build Coastguard Worker 	  CONSUME (8);
4937*7304104dSAndroid Build Coastguard Worker 	  data += 8;
4938*7304104dSAndroid Build Coastguard Worker 	  offset += 9;
4939*7304104dSAndroid Build Coastguard Worker 	  break;
4940*7304104dSAndroid Build Coastguard Worker 
4941*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const1s:
4942*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
4943*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4944*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
4945*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4946*7304104dSAndroid Build Coastguard Worker 		  op_name, *((int8_t *) data));
4947*7304104dSAndroid Build Coastguard Worker 	  ++data;
4948*7304104dSAndroid Build Coastguard Worker 	  --len;
4949*7304104dSAndroid Build Coastguard Worker 	  offset += 2;
4950*7304104dSAndroid Build Coastguard Worker 	  break;
4951*7304104dSAndroid Build Coastguard Worker 
4952*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const2s:
4953*7304104dSAndroid Build Coastguard Worker 	  NEED (2);
4954*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4955*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
4956*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4957*7304104dSAndroid Build Coastguard Worker 		  op_name, read_2sbyte_unaligned (dbg, data));
4958*7304104dSAndroid Build Coastguard Worker 	  CONSUME (2);
4959*7304104dSAndroid Build Coastguard Worker 	  data += 2;
4960*7304104dSAndroid Build Coastguard Worker 	  offset += 3;
4961*7304104dSAndroid Build Coastguard Worker 	  break;
4962*7304104dSAndroid Build Coastguard Worker 
4963*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const4s:
4964*7304104dSAndroid Build Coastguard Worker 	  NEED (4);
4965*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4966*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
4967*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4968*7304104dSAndroid Build Coastguard Worker 		  op_name, read_4sbyte_unaligned (dbg, data));
4969*7304104dSAndroid Build Coastguard Worker 	  CONSUME (4);
4970*7304104dSAndroid Build Coastguard Worker 	  data += 4;
4971*7304104dSAndroid Build Coastguard Worker 	  offset += 5;
4972*7304104dSAndroid Build Coastguard Worker 	  break;
4973*7304104dSAndroid Build Coastguard Worker 
4974*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const8s:
4975*7304104dSAndroid Build Coastguard Worker 	  NEED (8);
4976*7304104dSAndroid Build Coastguard Worker 	  // XXX value might be modified by relocation
4977*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
4978*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
4979*7304104dSAndroid Build Coastguard Worker 		  op_name, read_8sbyte_unaligned (dbg, data));
4980*7304104dSAndroid Build Coastguard Worker 	  CONSUME (8);
4981*7304104dSAndroid Build Coastguard Worker 	  data += 8;
4982*7304104dSAndroid Build Coastguard Worker 	  offset += 9;
4983*7304104dSAndroid Build Coastguard Worker 	  break;
4984*7304104dSAndroid Build Coastguard Worker 
4985*7304104dSAndroid Build Coastguard Worker 	case DW_OP_piece:
4986*7304104dSAndroid Build Coastguard Worker 	case DW_OP_regx:
4987*7304104dSAndroid Build Coastguard Worker 	case DW_OP_plus_uconst:
4988*7304104dSAndroid Build Coastguard Worker 	case DW_OP_constu:;
4989*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *start = data;
4990*7304104dSAndroid Build Coastguard Worker 	  uint64_t uleb;
4991*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
4992*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
4993*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
4994*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, uleb);
4995*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
4996*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
4997*7304104dSAndroid Build Coastguard Worker 	  break;
4998*7304104dSAndroid Build Coastguard Worker 
4999*7304104dSAndroid Build Coastguard Worker 	case DW_OP_addrx:
5000*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_addr_index:
5001*7304104dSAndroid Build Coastguard Worker 	case DW_OP_constx:
5002*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_const_index:;
5003*7304104dSAndroid Build Coastguard Worker 	  start = data;
5004*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5005*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5006*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
5007*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, uleb);
5008*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5009*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5010*7304104dSAndroid Build Coastguard Worker 	  if (get_indexed_addr (cu, uleb, &addr) != 0)
5011*7304104dSAndroid Build Coastguard Worker 	    printf ("???\n");
5012*7304104dSAndroid Build Coastguard Worker 	  else
5013*7304104dSAndroid Build Coastguard Worker 	    {
5014*7304104dSAndroid Build Coastguard Worker 	      print_dwarf_addr (dwflmod, 0, addr, addr);
5015*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
5016*7304104dSAndroid Build Coastguard Worker 	    }
5017*7304104dSAndroid Build Coastguard Worker 	  break;
5018*7304104dSAndroid Build Coastguard Worker 
5019*7304104dSAndroid Build Coastguard Worker 	case DW_OP_bit_piece:
5020*7304104dSAndroid Build Coastguard Worker 	  start = data;
5021*7304104dSAndroid Build Coastguard Worker 	  uint64_t uleb2;
5022*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5023*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5024*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5025*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb2, data, data + len);
5026*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
5027*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
5028*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5029*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5030*7304104dSAndroid Build Coastguard Worker 	  break;
5031*7304104dSAndroid Build Coastguard Worker 
5032*7304104dSAndroid Build Coastguard Worker 	case DW_OP_fbreg:
5033*7304104dSAndroid Build Coastguard Worker 	case DW_OP_breg0 ... DW_OP_breg31:
5034*7304104dSAndroid Build Coastguard Worker 	case DW_OP_consts:
5035*7304104dSAndroid Build Coastguard Worker 	  start = data;
5036*7304104dSAndroid Build Coastguard Worker 	  int64_t sleb;
5037*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5038*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (sleb, data, data + len);
5039*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
5040*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, sleb);
5041*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5042*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5043*7304104dSAndroid Build Coastguard Worker 	  break;
5044*7304104dSAndroid Build Coastguard Worker 
5045*7304104dSAndroid Build Coastguard Worker 	case DW_OP_bregx:
5046*7304104dSAndroid Build Coastguard Worker 	  start = data;
5047*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5048*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5049*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5050*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (sleb, data, data + len);
5051*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
5052*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, uleb, sleb);
5053*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5054*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5055*7304104dSAndroid Build Coastguard Worker 	  break;
5056*7304104dSAndroid Build Coastguard Worker 
5057*7304104dSAndroid Build Coastguard Worker 	case DW_OP_call2:
5058*7304104dSAndroid Build Coastguard Worker 	  NEED (2);
5059*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
5060*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name,
5061*7304104dSAndroid Build Coastguard Worker 		  read_2ubyte_unaligned (dbg, data));
5062*7304104dSAndroid Build Coastguard Worker 	  CONSUME (2);
5063*7304104dSAndroid Build Coastguard Worker 	  data += 2;
5064*7304104dSAndroid Build Coastguard Worker 	  offset += 3;
5065*7304104dSAndroid Build Coastguard Worker 	  break;
5066*7304104dSAndroid Build Coastguard Worker 
5067*7304104dSAndroid Build Coastguard Worker 	case DW_OP_call4:
5068*7304104dSAndroid Build Coastguard Worker 	  NEED (4);
5069*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
5070*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name,
5071*7304104dSAndroid Build Coastguard Worker 		  read_4ubyte_unaligned (dbg, data));
5072*7304104dSAndroid Build Coastguard Worker 	  CONSUME (4);
5073*7304104dSAndroid Build Coastguard Worker 	  data += 4;
5074*7304104dSAndroid Build Coastguard Worker 	  offset += 5;
5075*7304104dSAndroid Build Coastguard Worker 	  break;
5076*7304104dSAndroid Build Coastguard Worker 
5077*7304104dSAndroid Build Coastguard Worker 	case DW_OP_skip:
5078*7304104dSAndroid Build Coastguard Worker 	case DW_OP_bra:
5079*7304104dSAndroid Build Coastguard Worker 	  NEED (2);
5080*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
5081*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name,
5082*7304104dSAndroid Build Coastguard Worker 		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
5083*7304104dSAndroid Build Coastguard Worker 	  CONSUME (2);
5084*7304104dSAndroid Build Coastguard Worker 	  data += 2;
5085*7304104dSAndroid Build Coastguard Worker 	  offset += 3;
5086*7304104dSAndroid Build Coastguard Worker 	  break;
5087*7304104dSAndroid Build Coastguard Worker 
5088*7304104dSAndroid Build Coastguard Worker 	case DW_OP_implicit_value:
5089*7304104dSAndroid Build Coastguard Worker 	  start = data;
5090*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5091*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5092*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s: ",
5093*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name);
5094*7304104dSAndroid Build Coastguard Worker 	  NEED (uleb);
5095*7304104dSAndroid Build Coastguard Worker 	  print_block (uleb, data);
5096*7304104dSAndroid Build Coastguard Worker 	  data += uleb;
5097*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5098*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5099*7304104dSAndroid Build Coastguard Worker 	  break;
5100*7304104dSAndroid Build Coastguard Worker 
5101*7304104dSAndroid Build Coastguard Worker 	case DW_OP_implicit_pointer:
5102*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_implicit_pointer:
5103*7304104dSAndroid Build Coastguard Worker 	  /* DIE offset operand.  */
5104*7304104dSAndroid Build Coastguard Worker 	  start = data;
5105*7304104dSAndroid Build Coastguard Worker 	  NEED (ref_size);
5106*7304104dSAndroid Build Coastguard Worker 	  if (ref_size != 4 && ref_size != 8)
5107*7304104dSAndroid Build Coastguard Worker 	    goto invalid; /* Cannot be used in CFA.  */
5108*7304104dSAndroid Build Coastguard Worker 	  if (ref_size == 4)
5109*7304104dSAndroid Build Coastguard Worker 	    addr = read_4ubyte_unaligned (dbg, data);
5110*7304104dSAndroid Build Coastguard Worker 	  else
5111*7304104dSAndroid Build Coastguard Worker 	    addr = read_8ubyte_unaligned (dbg, data);
5112*7304104dSAndroid Build Coastguard Worker 	  data += ref_size;
5113*7304104dSAndroid Build Coastguard Worker 	  /* Byte offset operand.  */
5114*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5115*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (sleb, data, data + len);
5116*7304104dSAndroid Build Coastguard Worker 
5117*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
5118*7304104dSAndroid Build Coastguard Worker 		  indent, "", (intmax_t) offset,
5119*7304104dSAndroid Build Coastguard Worker 		  op_name, (uintmax_t) addr, sleb);
5120*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5121*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5122*7304104dSAndroid Build Coastguard Worker 	  break;
5123*7304104dSAndroid Build Coastguard Worker 
5124*7304104dSAndroid Build Coastguard Worker 	case DW_OP_entry_value:
5125*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_entry_value:
5126*7304104dSAndroid Build Coastguard Worker 	  /* Size plus expression block.  */
5127*7304104dSAndroid Build Coastguard Worker 	  start = data;
5128*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5129*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5130*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s:\n",
5131*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name);
5132*7304104dSAndroid Build Coastguard Worker 	  NEED (uleb);
5133*7304104dSAndroid Build Coastguard Worker 	  print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
5134*7304104dSAndroid Build Coastguard Worker 		     addrsize, offset_size, cu, uleb, data);
5135*7304104dSAndroid Build Coastguard Worker 	  data += uleb;
5136*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5137*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5138*7304104dSAndroid Build Coastguard Worker 	  break;
5139*7304104dSAndroid Build Coastguard Worker 
5140*7304104dSAndroid Build Coastguard Worker 	case DW_OP_const_type:
5141*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_const_type:
5142*7304104dSAndroid Build Coastguard Worker 	  /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
5143*7304104dSAndroid Build Coastguard Worker 	     unsigned size plus block.  */
5144*7304104dSAndroid Build Coastguard Worker 	  start = data;
5145*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5146*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5147*7304104dSAndroid Build Coastguard Worker 	  if (! print_unresolved_addresses && cu != NULL)
5148*7304104dSAndroid Build Coastguard Worker 	    uleb += cu->start;
5149*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5150*7304104dSAndroid Build Coastguard Worker 	  uint8_t usize = *(uint8_t *) data++;
5151*7304104dSAndroid Build Coastguard Worker 	  NEED (usize);
5152*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
5153*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, uleb);
5154*7304104dSAndroid Build Coastguard Worker 	  print_block (usize, data);
5155*7304104dSAndroid Build Coastguard Worker 	  data += usize;
5156*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5157*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5158*7304104dSAndroid Build Coastguard Worker 	  break;
5159*7304104dSAndroid Build Coastguard Worker 
5160*7304104dSAndroid Build Coastguard Worker 	case DW_OP_regval_type:
5161*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_regval_type:
5162*7304104dSAndroid Build Coastguard Worker 	  /* uleb128 register number, uleb128 CU relative
5163*7304104dSAndroid Build Coastguard Worker 	     DW_TAG_base_type DIE offset.  */
5164*7304104dSAndroid Build Coastguard Worker 	  start = data;
5165*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5166*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5167*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5168*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb2, data, data + len);
5169*7304104dSAndroid Build Coastguard Worker 	  if (! print_unresolved_addresses && cu != NULL)
5170*7304104dSAndroid Build Coastguard Worker 	    uleb2 += cu->start;
5171*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
5172*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
5173*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5174*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5175*7304104dSAndroid Build Coastguard Worker 	  break;
5176*7304104dSAndroid Build Coastguard Worker 
5177*7304104dSAndroid Build Coastguard Worker 	case DW_OP_deref_type:
5178*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_deref_type:
5179*7304104dSAndroid Build Coastguard Worker 	  /* 1-byte unsigned size of value, uleb128 CU relative
5180*7304104dSAndroid Build Coastguard Worker 	     DW_TAG_base_type DIE offset.  */
5181*7304104dSAndroid Build Coastguard Worker 	  start = data;
5182*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5183*7304104dSAndroid Build Coastguard Worker 	  usize = *(uint8_t *) data++;
5184*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5185*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5186*7304104dSAndroid Build Coastguard Worker 	  if (! print_unresolved_addresses && cu != NULL)
5187*7304104dSAndroid Build Coastguard Worker 	    uleb += cu->start;
5188*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
5189*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
5190*7304104dSAndroid Build Coastguard Worker 		  op_name, usize, uleb);
5191*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5192*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5193*7304104dSAndroid Build Coastguard Worker 	  break;
5194*7304104dSAndroid Build Coastguard Worker 
5195*7304104dSAndroid Build Coastguard Worker 	case DW_OP_xderef_type:
5196*7304104dSAndroid Build Coastguard Worker 	  /* 1-byte unsigned size of value, uleb128 base_type DIE offset.  */
5197*7304104dSAndroid Build Coastguard Worker 	  start = data;
5198*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5199*7304104dSAndroid Build Coastguard Worker 	  usize = *(uint8_t *) data++;
5200*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5201*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5202*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
5203*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset,
5204*7304104dSAndroid Build Coastguard Worker 		  op_name, usize, uleb);
5205*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5206*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5207*7304104dSAndroid Build Coastguard Worker 	  break;
5208*7304104dSAndroid Build Coastguard Worker 
5209*7304104dSAndroid Build Coastguard Worker 	case DW_OP_convert:
5210*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_convert:
5211*7304104dSAndroid Build Coastguard Worker 	case DW_OP_reinterpret:
5212*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_reinterpret:
5213*7304104dSAndroid Build Coastguard Worker 	  /* uleb128 CU relative offset to DW_TAG_base_type, or zero
5214*7304104dSAndroid Build Coastguard Worker 	     for conversion to untyped.  */
5215*7304104dSAndroid Build Coastguard Worker 	  start = data;
5216*7304104dSAndroid Build Coastguard Worker 	  NEED (1);
5217*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (uleb, data, data + len);
5218*7304104dSAndroid Build Coastguard Worker 	  if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
5219*7304104dSAndroid Build Coastguard Worker 	    uleb += cu->start;
5220*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
5221*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, uleb);
5222*7304104dSAndroid Build Coastguard Worker 	  CONSUME (data - start);
5223*7304104dSAndroid Build Coastguard Worker 	  offset += 1 + (data - start);
5224*7304104dSAndroid Build Coastguard Worker 	  break;
5225*7304104dSAndroid Build Coastguard Worker 
5226*7304104dSAndroid Build Coastguard Worker 	case DW_OP_GNU_parameter_ref:
5227*7304104dSAndroid Build Coastguard Worker 	  /* 4 byte CU relative reference to the abstract optimized away
5228*7304104dSAndroid Build Coastguard Worker 	     DW_TAG_formal_parameter.  */
5229*7304104dSAndroid Build Coastguard Worker 	  NEED (4);
5230*7304104dSAndroid Build Coastguard Worker 	  uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
5231*7304104dSAndroid Build Coastguard Worker 	  if (! print_unresolved_addresses && cu != NULL)
5232*7304104dSAndroid Build Coastguard Worker 	    param_off += cu->start;
5233*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
5234*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name, param_off);
5235*7304104dSAndroid Build Coastguard Worker 	  CONSUME (4);
5236*7304104dSAndroid Build Coastguard Worker 	  data += 4;
5237*7304104dSAndroid Build Coastguard Worker 	  offset += 5;
5238*7304104dSAndroid Build Coastguard Worker 	  break;
5239*7304104dSAndroid Build Coastguard Worker 
5240*7304104dSAndroid Build Coastguard Worker 	default:
5241*7304104dSAndroid Build Coastguard Worker 	  /* No Operand.  */
5242*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s[%2" PRIuMAX "] %s\n",
5243*7304104dSAndroid Build Coastguard Worker 		  indent, "", (uintmax_t) offset, op_name);
5244*7304104dSAndroid Build Coastguard Worker 	  ++offset;
5245*7304104dSAndroid Build Coastguard Worker 	  break;
5246*7304104dSAndroid Build Coastguard Worker 	}
5247*7304104dSAndroid Build Coastguard Worker 
5248*7304104dSAndroid Build Coastguard Worker       indent = indentrest;
5249*7304104dSAndroid Build Coastguard Worker       continue;
5250*7304104dSAndroid Build Coastguard Worker 
5251*7304104dSAndroid Build Coastguard Worker     invalid:
5252*7304104dSAndroid Build Coastguard Worker       printf (_("%*s[%2" PRIuMAX "] %s  <TRUNCATED>\n"),
5253*7304104dSAndroid Build Coastguard Worker 	      indent, "", (uintmax_t) offset, op_name);
5254*7304104dSAndroid Build Coastguard Worker       break;
5255*7304104dSAndroid Build Coastguard Worker     }
5256*7304104dSAndroid Build Coastguard Worker }
5257*7304104dSAndroid Build Coastguard Worker 
5258*7304104dSAndroid Build Coastguard Worker 
5259*7304104dSAndroid Build Coastguard Worker /* Turn the addresses into file offsets by using the phdrs.  */
5260*7304104dSAndroid Build Coastguard Worker static void
find_offsets(Elf * elf,GElf_Addr main_bias,size_t n,GElf_Addr addrs[n],GElf_Off offs[n])5261*7304104dSAndroid Build Coastguard Worker find_offsets(Elf *elf, GElf_Addr main_bias, size_t n,
5262*7304104dSAndroid Build Coastguard Worker                   GElf_Addr addrs[n], GElf_Off offs[n])
5263*7304104dSAndroid Build Coastguard Worker {
5264*7304104dSAndroid Build Coastguard Worker   size_t unsolved = n;
5265*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < phnum; ++i) {
5266*7304104dSAndroid Build Coastguard Worker     GElf_Phdr phdr_mem;
5267*7304104dSAndroid Build Coastguard Worker     GElf_Phdr *phdr = gelf_getphdr(elf, i, &phdr_mem);
5268*7304104dSAndroid Build Coastguard Worker     if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
5269*7304104dSAndroid Build Coastguard Worker       for (size_t j = 0; j < n; ++j)
5270*7304104dSAndroid Build Coastguard Worker         if (offs[j] == 0 && addrs[j] >= phdr->p_vaddr + main_bias &&
5271*7304104dSAndroid Build Coastguard Worker             addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz) {
5272*7304104dSAndroid Build Coastguard Worker           offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset;
5273*7304104dSAndroid Build Coastguard Worker           if (--unsolved == 0)
5274*7304104dSAndroid Build Coastguard Worker             break;
5275*7304104dSAndroid Build Coastguard Worker         }
5276*7304104dSAndroid Build Coastguard Worker   }
5277*7304104dSAndroid Build Coastguard Worker }
5278*7304104dSAndroid Build Coastguard Worker 
5279*7304104dSAndroid Build Coastguard Worker /* The dynamic segment (type PT_DYNAMIC), contains the .dynamic section.
5280*7304104dSAndroid Build Coastguard Worker    And .dynamic section contains an array of the dynamic structures.
5281*7304104dSAndroid Build Coastguard Worker    We use the array to get:
5282*7304104dSAndroid Build Coastguard Worker     DT_STRTAB: the address of the string table
5283*7304104dSAndroid Build Coastguard Worker     DT_SYMTAB: the address of the symbol table
5284*7304104dSAndroid Build Coastguard Worker     DT_STRSZ: the size, in bytes, of the string table
5285*7304104dSAndroid Build Coastguard Worker     ...  */
5286*7304104dSAndroid Build Coastguard Worker static void
get_dynscn_addrs(Elf * elf,GElf_Phdr * phdr,GElf_Addr addrs[i_max])5287*7304104dSAndroid Build Coastguard Worker get_dynscn_addrs(Elf *elf, GElf_Phdr *phdr, GElf_Addr addrs[i_max])
5288*7304104dSAndroid Build Coastguard Worker {
5289*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata_rawchunk(
5290*7304104dSAndroid Build Coastguard Worker     elf, phdr->p_offset, phdr->p_filesz, ELF_T_DYN);
5291*7304104dSAndroid Build Coastguard Worker 
5292*7304104dSAndroid Build Coastguard Worker   int dyn_idx = 0;
5293*7304104dSAndroid Build Coastguard Worker   for (;; ++dyn_idx) {
5294*7304104dSAndroid Build Coastguard Worker     GElf_Dyn dyn_mem;
5295*7304104dSAndroid Build Coastguard Worker     GElf_Dyn *dyn = gelf_getdyn(data, dyn_idx, &dyn_mem);
5296*7304104dSAndroid Build Coastguard Worker     /* DT_NULL Marks end of dynamic section.  */
5297*7304104dSAndroid Build Coastguard Worker     if (dyn == NULL || dyn->d_tag == DT_NULL)
5298*7304104dSAndroid Build Coastguard Worker       break;
5299*7304104dSAndroid Build Coastguard Worker 
5300*7304104dSAndroid Build Coastguard Worker     switch (dyn->d_tag) {
5301*7304104dSAndroid Build Coastguard Worker     case DT_SYMTAB:
5302*7304104dSAndroid Build Coastguard Worker       addrs[i_symtab] = dyn->d_un.d_ptr;
5303*7304104dSAndroid Build Coastguard Worker       break;
5304*7304104dSAndroid Build Coastguard Worker 
5305*7304104dSAndroid Build Coastguard Worker     case DT_HASH:
5306*7304104dSAndroid Build Coastguard Worker       addrs[i_hash] = dyn->d_un.d_ptr;
5307*7304104dSAndroid Build Coastguard Worker       break;
5308*7304104dSAndroid Build Coastguard Worker 
5309*7304104dSAndroid Build Coastguard Worker     case DT_GNU_HASH:
5310*7304104dSAndroid Build Coastguard Worker       addrs[i_gnu_hash] = dyn->d_un.d_ptr;
5311*7304104dSAndroid Build Coastguard Worker       break;
5312*7304104dSAndroid Build Coastguard Worker 
5313*7304104dSAndroid Build Coastguard Worker     case DT_STRTAB:
5314*7304104dSAndroid Build Coastguard Worker       addrs[i_strtab] = dyn->d_un.d_ptr;
5315*7304104dSAndroid Build Coastguard Worker       break;
5316*7304104dSAndroid Build Coastguard Worker 
5317*7304104dSAndroid Build Coastguard Worker     case DT_VERSYM:
5318*7304104dSAndroid Build Coastguard Worker       addrs[i_versym] = dyn->d_un.d_ptr;
5319*7304104dSAndroid Build Coastguard Worker       break;
5320*7304104dSAndroid Build Coastguard Worker 
5321*7304104dSAndroid Build Coastguard Worker     case DT_VERDEF:
5322*7304104dSAndroid Build Coastguard Worker       addrs[i_verdef] = dyn->d_un.d_ptr;
5323*7304104dSAndroid Build Coastguard Worker       break;
5324*7304104dSAndroid Build Coastguard Worker 
5325*7304104dSAndroid Build Coastguard Worker     case DT_VERDEFNUM:
5326*7304104dSAndroid Build Coastguard Worker       addrs[i_verdefnum] = dyn->d_un.d_val;
5327*7304104dSAndroid Build Coastguard Worker       break;
5328*7304104dSAndroid Build Coastguard Worker 
5329*7304104dSAndroid Build Coastguard Worker     case DT_VERNEED:
5330*7304104dSAndroid Build Coastguard Worker       addrs[i_verneed] = dyn->d_un.d_ptr;
5331*7304104dSAndroid Build Coastguard Worker       break;
5332*7304104dSAndroid Build Coastguard Worker 
5333*7304104dSAndroid Build Coastguard Worker     case DT_VERNEEDNUM:
5334*7304104dSAndroid Build Coastguard Worker       addrs[i_verneednum] = dyn->d_un.d_val;
5335*7304104dSAndroid Build Coastguard Worker       break;
5336*7304104dSAndroid Build Coastguard Worker 
5337*7304104dSAndroid Build Coastguard Worker     case DT_STRSZ:
5338*7304104dSAndroid Build Coastguard Worker       addrs[i_strsz] = dyn->d_un.d_val;
5339*7304104dSAndroid Build Coastguard Worker       break;
5340*7304104dSAndroid Build Coastguard Worker 
5341*7304104dSAndroid Build Coastguard Worker     case DT_SYMTAB_SHNDX:
5342*7304104dSAndroid Build Coastguard Worker       addrs[i_symtab_shndx] = dyn->d_un.d_ptr;
5343*7304104dSAndroid Build Coastguard Worker       break;
5344*7304104dSAndroid Build Coastguard Worker     }
5345*7304104dSAndroid Build Coastguard Worker   }
5346*7304104dSAndroid Build Coastguard Worker }
5347*7304104dSAndroid Build Coastguard Worker 
5348*7304104dSAndroid Build Coastguard Worker 
5349*7304104dSAndroid Build Coastguard Worker /* Use dynamic segment to get data for the string table section.  */
5350*7304104dSAndroid Build Coastguard Worker static Elf_Data *
get_dynscn_strtab(Elf * elf,GElf_Phdr * phdr)5351*7304104dSAndroid Build Coastguard Worker get_dynscn_strtab(Elf *elf, GElf_Phdr *phdr)
5352*7304104dSAndroid Build Coastguard Worker {
5353*7304104dSAndroid Build Coastguard Worker   Elf_Data *strtab_data;
5354*7304104dSAndroid Build Coastguard Worker   GElf_Addr addrs[i_max] = {0,};
5355*7304104dSAndroid Build Coastguard Worker   GElf_Off offs[i_max] = {0,};
5356*7304104dSAndroid Build Coastguard Worker   get_dynscn_addrs(elf, phdr, addrs);
5357*7304104dSAndroid Build Coastguard Worker   find_offsets(elf, 0, i_max, addrs, offs);
5358*7304104dSAndroid Build Coastguard Worker   strtab_data = elf_getdata_rawchunk(
5359*7304104dSAndroid Build Coastguard Worker           elf, offs[i_strtab], addrs[i_strsz], ELF_T_BYTE);
5360*7304104dSAndroid Build Coastguard Worker   return strtab_data;
5361*7304104dSAndroid Build Coastguard Worker }
5362*7304104dSAndroid Build Coastguard Worker 
5363*7304104dSAndroid Build Coastguard Worker 
5364*7304104dSAndroid Build Coastguard Worker struct listptr
5365*7304104dSAndroid Build Coastguard Worker {
5366*7304104dSAndroid Build Coastguard Worker   Dwarf_Off offset:(64 - 3);
5367*7304104dSAndroid Build Coastguard Worker   bool addr64:1;
5368*7304104dSAndroid Build Coastguard Worker   bool dwarf64:1;
5369*7304104dSAndroid Build Coastguard Worker   bool warned:1;
5370*7304104dSAndroid Build Coastguard Worker   struct Dwarf_CU *cu;
5371*7304104dSAndroid Build Coastguard Worker   unsigned int attr;
5372*7304104dSAndroid Build Coastguard Worker };
5373*7304104dSAndroid Build Coastguard Worker 
5374*7304104dSAndroid Build Coastguard Worker #define listptr_offset_size(p)	((p)->dwarf64 ? 8 : 4)
5375*7304104dSAndroid Build Coastguard Worker #define listptr_address_size(p)	((p)->addr64 ? 8 : 4)
5376*7304104dSAndroid Build Coastguard Worker 
5377*7304104dSAndroid Build Coastguard Worker static Dwarf_Addr
cudie_base(Dwarf_Die * cudie)5378*7304104dSAndroid Build Coastguard Worker cudie_base (Dwarf_Die *cudie)
5379*7304104dSAndroid Build Coastguard Worker {
5380*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr base;
5381*7304104dSAndroid Build Coastguard Worker   /* Find the base address of the compilation unit.  It will normally
5382*7304104dSAndroid Build Coastguard Worker      be specified by DW_AT_low_pc.  In DWARF-3 draft 4, the base
5383*7304104dSAndroid Build Coastguard Worker      address could be overridden by DW_AT_entry_pc.  It's been
5384*7304104dSAndroid Build Coastguard Worker      removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
5385*7304104dSAndroid Build Coastguard Worker      compilation units with discontinuous ranges.  */
5386*7304104dSAndroid Build Coastguard Worker   if (unlikely (dwarf_lowpc (cudie, &base) != 0))
5387*7304104dSAndroid Build Coastguard Worker     {
5388*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute attr_mem;
5389*7304104dSAndroid Build Coastguard Worker       if (dwarf_formaddr (dwarf_attr (cudie, DW_AT_entry_pc, &attr_mem),
5390*7304104dSAndroid Build Coastguard Worker 			  &base) != 0)
5391*7304104dSAndroid Build Coastguard Worker 	base = 0;
5392*7304104dSAndroid Build Coastguard Worker     }
5393*7304104dSAndroid Build Coastguard Worker   return base;
5394*7304104dSAndroid Build Coastguard Worker }
5395*7304104dSAndroid Build Coastguard Worker 
5396*7304104dSAndroid Build Coastguard Worker static Dwarf_Addr
listptr_base(struct listptr * p)5397*7304104dSAndroid Build Coastguard Worker listptr_base (struct listptr *p)
5398*7304104dSAndroid Build Coastguard Worker {
5399*7304104dSAndroid Build Coastguard Worker   Dwarf_Die cu = CUDIE (p->cu);
5400*7304104dSAndroid Build Coastguard Worker   return cudie_base (&cu);
5401*7304104dSAndroid Build Coastguard Worker }
5402*7304104dSAndroid Build Coastguard Worker 
5403*7304104dSAndroid Build Coastguard Worker /* To store the name used in compare_listptr */
5404*7304104dSAndroid Build Coastguard Worker static const char *sort_listptr_name;
5405*7304104dSAndroid Build Coastguard Worker 
5406*7304104dSAndroid Build Coastguard Worker static int
compare_listptr(const void * a,const void * b)5407*7304104dSAndroid Build Coastguard Worker compare_listptr (const void *a, const void *b)
5408*7304104dSAndroid Build Coastguard Worker {
5409*7304104dSAndroid Build Coastguard Worker   const char *name = sort_listptr_name;
5410*7304104dSAndroid Build Coastguard Worker   struct listptr *p1 = (void *) a;
5411*7304104dSAndroid Build Coastguard Worker   struct listptr *p2 = (void *) b;
5412*7304104dSAndroid Build Coastguard Worker 
5413*7304104dSAndroid Build Coastguard Worker   if (p1->offset < p2->offset)
5414*7304104dSAndroid Build Coastguard Worker     return -1;
5415*7304104dSAndroid Build Coastguard Worker   if (p1->offset > p2->offset)
5416*7304104dSAndroid Build Coastguard Worker     return 1;
5417*7304104dSAndroid Build Coastguard Worker 
5418*7304104dSAndroid Build Coastguard Worker   if (!p1->warned && !p2->warned)
5419*7304104dSAndroid Build Coastguard Worker     {
5420*7304104dSAndroid Build Coastguard Worker       if (p1->addr64 != p2->addr64)
5421*7304104dSAndroid Build Coastguard Worker 	{
5422*7304104dSAndroid Build Coastguard Worker 	  p1->warned = p2->warned = true;
5423*7304104dSAndroid Build Coastguard Worker 	  error (0, 0,
5424*7304104dSAndroid Build Coastguard Worker 		 _("%s %#" PRIx64 " used with different address sizes"),
5425*7304104dSAndroid Build Coastguard Worker 		 name, (uint64_t) p1->offset);
5426*7304104dSAndroid Build Coastguard Worker 	}
5427*7304104dSAndroid Build Coastguard Worker       if (p1->dwarf64 != p2->dwarf64)
5428*7304104dSAndroid Build Coastguard Worker 	{
5429*7304104dSAndroid Build Coastguard Worker 	  p1->warned = p2->warned = true;
5430*7304104dSAndroid Build Coastguard Worker 	  error (0, 0,
5431*7304104dSAndroid Build Coastguard Worker 		 _("%s %#" PRIx64 " used with different offset sizes"),
5432*7304104dSAndroid Build Coastguard Worker 		 name, (uint64_t) p1->offset);
5433*7304104dSAndroid Build Coastguard Worker 	}
5434*7304104dSAndroid Build Coastguard Worker       if (listptr_base (p1) != listptr_base (p2))
5435*7304104dSAndroid Build Coastguard Worker 	{
5436*7304104dSAndroid Build Coastguard Worker 	  p1->warned = p2->warned = true;
5437*7304104dSAndroid Build Coastguard Worker 	  error (0, 0,
5438*7304104dSAndroid Build Coastguard Worker 		 _("%s %#" PRIx64 " used with different base addresses"),
5439*7304104dSAndroid Build Coastguard Worker 		 name, (uint64_t) p1->offset);
5440*7304104dSAndroid Build Coastguard Worker 	}
5441*7304104dSAndroid Build Coastguard Worker       if (p1->attr != p2 ->attr)
5442*7304104dSAndroid Build Coastguard Worker 	{
5443*7304104dSAndroid Build Coastguard Worker 	  p1->warned = p2->warned = true;
5444*7304104dSAndroid Build Coastguard Worker 	  error (0, 0,
5445*7304104dSAndroid Build Coastguard Worker 		 _("%s %#" PRIx64
5446*7304104dSAndroid Build Coastguard Worker 			  " used with different attribute %s and %s"),
5447*7304104dSAndroid Build Coastguard Worker 		 name, (uint64_t) p1->offset, dwarf_attr_name (p1->attr),
5448*7304104dSAndroid Build Coastguard Worker 		 dwarf_attr_name (p2->attr));
5449*7304104dSAndroid Build Coastguard Worker 	}
5450*7304104dSAndroid Build Coastguard Worker     }
5451*7304104dSAndroid Build Coastguard Worker 
5452*7304104dSAndroid Build Coastguard Worker   return 0;
5453*7304104dSAndroid Build Coastguard Worker }
5454*7304104dSAndroid Build Coastguard Worker 
5455*7304104dSAndroid Build Coastguard Worker struct listptr_table
5456*7304104dSAndroid Build Coastguard Worker {
5457*7304104dSAndroid Build Coastguard Worker   size_t n;
5458*7304104dSAndroid Build Coastguard Worker   size_t alloc;
5459*7304104dSAndroid Build Coastguard Worker   struct listptr *table;
5460*7304104dSAndroid Build Coastguard Worker };
5461*7304104dSAndroid Build Coastguard Worker 
5462*7304104dSAndroid Build Coastguard Worker static struct listptr_table known_locsptr;
5463*7304104dSAndroid Build Coastguard Worker static struct listptr_table known_loclistsptr;
5464*7304104dSAndroid Build Coastguard Worker static struct listptr_table known_rangelistptr;
5465*7304104dSAndroid Build Coastguard Worker static struct listptr_table known_rnglistptr;
5466*7304104dSAndroid Build Coastguard Worker static struct listptr_table known_addrbases;
5467*7304104dSAndroid Build Coastguard Worker static struct listptr_table known_stroffbases;
5468*7304104dSAndroid Build Coastguard Worker 
5469*7304104dSAndroid Build Coastguard Worker static void
reset_listptr(struct listptr_table * table)5470*7304104dSAndroid Build Coastguard Worker reset_listptr (struct listptr_table *table)
5471*7304104dSAndroid Build Coastguard Worker {
5472*7304104dSAndroid Build Coastguard Worker   free (table->table);
5473*7304104dSAndroid Build Coastguard Worker   table->table = NULL;
5474*7304104dSAndroid Build Coastguard Worker   table->n = table->alloc = 0;
5475*7304104dSAndroid Build Coastguard Worker }
5476*7304104dSAndroid Build Coastguard Worker 
5477*7304104dSAndroid Build Coastguard Worker /* Returns false if offset doesn't fit.  See struct listptr.  */
5478*7304104dSAndroid Build Coastguard Worker static bool
notice_listptr(enum section_e section,struct listptr_table * table,uint_fast8_t address_size,uint_fast8_t offset_size,struct Dwarf_CU * cu,Dwarf_Off offset,unsigned int attr)5479*7304104dSAndroid Build Coastguard Worker notice_listptr (enum section_e section, struct listptr_table *table,
5480*7304104dSAndroid Build Coastguard Worker 		uint_fast8_t address_size, uint_fast8_t offset_size,
5481*7304104dSAndroid Build Coastguard Worker 		struct Dwarf_CU *cu, Dwarf_Off offset, unsigned int attr)
5482*7304104dSAndroid Build Coastguard Worker {
5483*7304104dSAndroid Build Coastguard Worker   if (print_debug_sections & section)
5484*7304104dSAndroid Build Coastguard Worker     {
5485*7304104dSAndroid Build Coastguard Worker       if (table->n == table->alloc)
5486*7304104dSAndroid Build Coastguard Worker 	{
5487*7304104dSAndroid Build Coastguard Worker 	  if (table->alloc == 0)
5488*7304104dSAndroid Build Coastguard Worker 	    table->alloc = 128;
5489*7304104dSAndroid Build Coastguard Worker 	  else
5490*7304104dSAndroid Build Coastguard Worker 	    table->alloc *= 2;
5491*7304104dSAndroid Build Coastguard Worker 	  table->table = xrealloc (table->table,
5492*7304104dSAndroid Build Coastguard Worker 				   table->alloc * sizeof table->table[0]);
5493*7304104dSAndroid Build Coastguard Worker 	}
5494*7304104dSAndroid Build Coastguard Worker 
5495*7304104dSAndroid Build Coastguard Worker       struct listptr *p = &table->table[table->n++];
5496*7304104dSAndroid Build Coastguard Worker 
5497*7304104dSAndroid Build Coastguard Worker       *p = (struct listptr)
5498*7304104dSAndroid Build Coastguard Worker 	{
5499*7304104dSAndroid Build Coastguard Worker 	  .addr64 = address_size == 8,
5500*7304104dSAndroid Build Coastguard Worker 	  .dwarf64 = offset_size == 8,
5501*7304104dSAndroid Build Coastguard Worker 	  .offset = offset,
5502*7304104dSAndroid Build Coastguard Worker 	  .cu = cu,
5503*7304104dSAndroid Build Coastguard Worker 	  .attr = attr
5504*7304104dSAndroid Build Coastguard Worker 	};
5505*7304104dSAndroid Build Coastguard Worker 
5506*7304104dSAndroid Build Coastguard Worker       if (p->offset != offset)
5507*7304104dSAndroid Build Coastguard Worker 	{
5508*7304104dSAndroid Build Coastguard Worker 	  table->n--;
5509*7304104dSAndroid Build Coastguard Worker 	  return false;
5510*7304104dSAndroid Build Coastguard Worker 	}
5511*7304104dSAndroid Build Coastguard Worker     }
5512*7304104dSAndroid Build Coastguard Worker   return true;
5513*7304104dSAndroid Build Coastguard Worker }
5514*7304104dSAndroid Build Coastguard Worker 
5515*7304104dSAndroid Build Coastguard Worker static void
sort_listptr(struct listptr_table * table,const char * name)5516*7304104dSAndroid Build Coastguard Worker sort_listptr (struct listptr_table *table, const char *name)
5517*7304104dSAndroid Build Coastguard Worker {
5518*7304104dSAndroid Build Coastguard Worker   if (table->n > 0)
5519*7304104dSAndroid Build Coastguard Worker     {
5520*7304104dSAndroid Build Coastguard Worker       sort_listptr_name = name;
5521*7304104dSAndroid Build Coastguard Worker       qsort (table->table, table->n, sizeof table->table[0],
5522*7304104dSAndroid Build Coastguard Worker 	     &compare_listptr);
5523*7304104dSAndroid Build Coastguard Worker     }
5524*7304104dSAndroid Build Coastguard Worker }
5525*7304104dSAndroid Build Coastguard Worker 
5526*7304104dSAndroid Build Coastguard Worker static bool
skip_listptr_hole(struct listptr_table * table,size_t * idxp,uint_fast8_t * address_sizep,uint_fast8_t * offset_sizep,Dwarf_Addr * base,struct Dwarf_CU ** cu,ptrdiff_t offset,unsigned char ** readp,unsigned char * endp,unsigned int * attr)5527*7304104dSAndroid Build Coastguard Worker skip_listptr_hole (struct listptr_table *table, size_t *idxp,
5528*7304104dSAndroid Build Coastguard Worker 		   uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
5529*7304104dSAndroid Build Coastguard Worker 		   Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
5530*7304104dSAndroid Build Coastguard Worker 		   unsigned char **readp, unsigned char *endp,
5531*7304104dSAndroid Build Coastguard Worker 		   unsigned int *attr)
5532*7304104dSAndroid Build Coastguard Worker {
5533*7304104dSAndroid Build Coastguard Worker   if (table->n == 0)
5534*7304104dSAndroid Build Coastguard Worker     return false;
5535*7304104dSAndroid Build Coastguard Worker 
5536*7304104dSAndroid Build Coastguard Worker   while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
5537*7304104dSAndroid Build Coastguard Worker     ++*idxp;
5538*7304104dSAndroid Build Coastguard Worker 
5539*7304104dSAndroid Build Coastguard Worker   struct listptr *p = &table->table[*idxp];
5540*7304104dSAndroid Build Coastguard Worker 
5541*7304104dSAndroid Build Coastguard Worker   if (*idxp == table->n
5542*7304104dSAndroid Build Coastguard Worker       || p->offset >= (Dwarf_Off) (endp - *readp + offset))
5543*7304104dSAndroid Build Coastguard Worker     {
5544*7304104dSAndroid Build Coastguard Worker       *readp = endp;
5545*7304104dSAndroid Build Coastguard Worker       printf (_(" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
5546*7304104dSAndroid Build Coastguard Worker 	      offset);
5547*7304104dSAndroid Build Coastguard Worker       return true;
5548*7304104dSAndroid Build Coastguard Worker     }
5549*7304104dSAndroid Build Coastguard Worker 
5550*7304104dSAndroid Build Coastguard Worker   if (p->offset != (Dwarf_Off) offset)
5551*7304104dSAndroid Build Coastguard Worker     {
5552*7304104dSAndroid Build Coastguard Worker       *readp += p->offset - offset;
5553*7304104dSAndroid Build Coastguard Worker       printf (_(" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
5554*7304104dSAndroid Build Coastguard Worker 	      offset, (Dwarf_Off) p->offset - offset);
5555*7304104dSAndroid Build Coastguard Worker       return true;
5556*7304104dSAndroid Build Coastguard Worker     }
5557*7304104dSAndroid Build Coastguard Worker 
5558*7304104dSAndroid Build Coastguard Worker   if (address_sizep != NULL)
5559*7304104dSAndroid Build Coastguard Worker     *address_sizep = listptr_address_size (p);
5560*7304104dSAndroid Build Coastguard Worker   if (offset_sizep != NULL)
5561*7304104dSAndroid Build Coastguard Worker     *offset_sizep = listptr_offset_size (p);
5562*7304104dSAndroid Build Coastguard Worker   if (base != NULL)
5563*7304104dSAndroid Build Coastguard Worker     *base = listptr_base (p);
5564*7304104dSAndroid Build Coastguard Worker   if (cu != NULL)
5565*7304104dSAndroid Build Coastguard Worker     *cu = p->cu;
5566*7304104dSAndroid Build Coastguard Worker   if (attr != NULL)
5567*7304104dSAndroid Build Coastguard Worker     *attr = p->attr;
5568*7304104dSAndroid Build Coastguard Worker 
5569*7304104dSAndroid Build Coastguard Worker   return false;
5570*7304104dSAndroid Build Coastguard Worker }
5571*7304104dSAndroid Build Coastguard Worker 
5572*7304104dSAndroid Build Coastguard Worker static Dwarf_Off
next_listptr_offset(struct listptr_table * table,size_t * idxp,Dwarf_Off off)5573*7304104dSAndroid Build Coastguard Worker next_listptr_offset (struct listptr_table *table, size_t *idxp, Dwarf_Off off)
5574*7304104dSAndroid Build Coastguard Worker {
5575*7304104dSAndroid Build Coastguard Worker   /* Note that multiple attributes could in theory point to the same loclist
5576*7304104dSAndroid Build Coastguard Worker      offset, so make sure we pick one that is bigger than the current one.
5577*7304104dSAndroid Build Coastguard Worker      The table is sorted on offset.  */
5578*7304104dSAndroid Build Coastguard Worker   if (*idxp < table->n)
5579*7304104dSAndroid Build Coastguard Worker     {
5580*7304104dSAndroid Build Coastguard Worker       while (++*idxp < table->n)
5581*7304104dSAndroid Build Coastguard Worker 	{
5582*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off next = table->table[*idxp].offset;
5583*7304104dSAndroid Build Coastguard Worker 	  if (next > off)
5584*7304104dSAndroid Build Coastguard Worker 	    return next;
5585*7304104dSAndroid Build Coastguard Worker 	}
5586*7304104dSAndroid Build Coastguard Worker     }
5587*7304104dSAndroid Build Coastguard Worker   return 0;
5588*7304104dSAndroid Build Coastguard Worker }
5589*7304104dSAndroid Build Coastguard Worker 
5590*7304104dSAndroid Build Coastguard Worker /* Returns the listptr associated with the given index, or NULL.  */
5591*7304104dSAndroid Build Coastguard Worker static struct listptr *
get_listptr(struct listptr_table * table,size_t idx)5592*7304104dSAndroid Build Coastguard Worker get_listptr (struct listptr_table *table, size_t idx)
5593*7304104dSAndroid Build Coastguard Worker {
5594*7304104dSAndroid Build Coastguard Worker   if (idx >= table->n)
5595*7304104dSAndroid Build Coastguard Worker     return NULL;
5596*7304104dSAndroid Build Coastguard Worker   return &table->table[idx];
5597*7304104dSAndroid Build Coastguard Worker }
5598*7304104dSAndroid Build Coastguard Worker 
5599*7304104dSAndroid Build Coastguard Worker /* Returns the next index, base address and CU associated with the
5600*7304104dSAndroid Build Coastguard Worker    list unit offsets.  If there is none false is returned, otherwise
5601*7304104dSAndroid Build Coastguard Worker    true.  Assumes the table has been sorted.  */
5602*7304104dSAndroid Build Coastguard Worker static bool
listptr_cu(struct listptr_table * table,size_t * idxp,Dwarf_Off start,Dwarf_Off end,Dwarf_Addr * base,struct Dwarf_CU ** cu)5603*7304104dSAndroid Build Coastguard Worker listptr_cu (struct listptr_table *table, size_t *idxp,
5604*7304104dSAndroid Build Coastguard Worker 	    Dwarf_Off start, Dwarf_Off end,
5605*7304104dSAndroid Build Coastguard Worker 	    Dwarf_Addr *base, struct Dwarf_CU **cu)
5606*7304104dSAndroid Build Coastguard Worker {
5607*7304104dSAndroid Build Coastguard Worker   while (*idxp < table->n
5608*7304104dSAndroid Build Coastguard Worker 	 && table->table[*idxp].offset < start)
5609*7304104dSAndroid Build Coastguard Worker     ++*idxp;
5610*7304104dSAndroid Build Coastguard Worker 
5611*7304104dSAndroid Build Coastguard Worker   if (*idxp < table->n
5612*7304104dSAndroid Build Coastguard Worker       && table->table[*idxp].offset >= start
5613*7304104dSAndroid Build Coastguard Worker       && table->table[*idxp].offset < end)
5614*7304104dSAndroid Build Coastguard Worker     {
5615*7304104dSAndroid Build Coastguard Worker       struct listptr *p = &table->table[*idxp];
5616*7304104dSAndroid Build Coastguard Worker       *base = listptr_base (p);
5617*7304104dSAndroid Build Coastguard Worker       *cu = p->cu;
5618*7304104dSAndroid Build Coastguard Worker       return true;
5619*7304104dSAndroid Build Coastguard Worker     }
5620*7304104dSAndroid Build Coastguard Worker 
5621*7304104dSAndroid Build Coastguard Worker   return false;
5622*7304104dSAndroid Build Coastguard Worker }
5623*7304104dSAndroid Build Coastguard Worker 
5624*7304104dSAndroid Build Coastguard Worker /* Returns the next index with the current CU for the given attribute.
5625*7304104dSAndroid Build Coastguard Worker    If there is none false is returned, otherwise true.  Assumes the
5626*7304104dSAndroid Build Coastguard Worker    table has been sorted.  */
5627*7304104dSAndroid Build Coastguard Worker static bool
listptr_attr(struct listptr_table * table,size_t idxp,Dwarf_Off offset,unsigned int attr)5628*7304104dSAndroid Build Coastguard Worker listptr_attr (struct listptr_table *table, size_t idxp,
5629*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Off offset, unsigned int attr)
5630*7304104dSAndroid Build Coastguard Worker {
5631*7304104dSAndroid Build Coastguard Worker   struct listptr *listptr;
5632*7304104dSAndroid Build Coastguard Worker   do
5633*7304104dSAndroid Build Coastguard Worker     {
5634*7304104dSAndroid Build Coastguard Worker       listptr = get_listptr (table, idxp);
5635*7304104dSAndroid Build Coastguard Worker       if (listptr == NULL)
5636*7304104dSAndroid Build Coastguard Worker 	return false;
5637*7304104dSAndroid Build Coastguard Worker 
5638*7304104dSAndroid Build Coastguard Worker       if (listptr->offset == offset && listptr->attr == attr)
5639*7304104dSAndroid Build Coastguard Worker 	return true;
5640*7304104dSAndroid Build Coastguard Worker 
5641*7304104dSAndroid Build Coastguard Worker       idxp++;
5642*7304104dSAndroid Build Coastguard Worker     }
5643*7304104dSAndroid Build Coastguard Worker   while (listptr->offset <= offset);
5644*7304104dSAndroid Build Coastguard Worker 
5645*7304104dSAndroid Build Coastguard Worker   return false;
5646*7304104dSAndroid Build Coastguard Worker }
5647*7304104dSAndroid Build Coastguard Worker 
5648*7304104dSAndroid Build Coastguard Worker static void
print_debug_abbrev_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)5649*7304104dSAndroid Build Coastguard Worker print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5650*7304104dSAndroid Build Coastguard Worker 			    Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
5651*7304104dSAndroid Build Coastguard Worker 			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5652*7304104dSAndroid Build Coastguard Worker {
5653*7304104dSAndroid Build Coastguard Worker   Elf_Data *elf_data = get_debug_elf_data (dbg, ebl, IDX_debug_abbrev, scn);
5654*7304104dSAndroid Build Coastguard Worker   if (elf_data == NULL)
5655*7304104dSAndroid Build Coastguard Worker     return;
5656*7304104dSAndroid Build Coastguard Worker 
5657*7304104dSAndroid Build Coastguard Worker   const size_t sh_size = elf_data->d_size;
5658*7304104dSAndroid Build Coastguard Worker 
5659*7304104dSAndroid Build Coastguard Worker   printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
5660*7304104dSAndroid Build Coastguard Worker 		   " [ Code]\n"),
5661*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
5662*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
5663*7304104dSAndroid Build Coastguard Worker 
5664*7304104dSAndroid Build Coastguard Worker   Dwarf_Off offset = 0;
5665*7304104dSAndroid Build Coastguard Worker   while (offset < sh_size)
5666*7304104dSAndroid Build Coastguard Worker     {
5667*7304104dSAndroid Build Coastguard Worker       printf (_("\nAbbreviation section at offset %" PRIu64 ":\n"),
5668*7304104dSAndroid Build Coastguard Worker 	      offset);
5669*7304104dSAndroid Build Coastguard Worker 
5670*7304104dSAndroid Build Coastguard Worker       while (1)
5671*7304104dSAndroid Build Coastguard Worker 	{
5672*7304104dSAndroid Build Coastguard Worker 	  size_t length;
5673*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Abbrev abbrev;
5674*7304104dSAndroid Build Coastguard Worker 
5675*7304104dSAndroid Build Coastguard Worker 	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
5676*7304104dSAndroid Build Coastguard Worker 	  if (res != 0)
5677*7304104dSAndroid Build Coastguard Worker 	    {
5678*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (res < 0))
5679*7304104dSAndroid Build Coastguard Worker 		{
5680*7304104dSAndroid Build Coastguard Worker 		  printf (_("\
5681*7304104dSAndroid Build Coastguard Worker  *** error while reading abbreviation: %s\n"),
5682*7304104dSAndroid Build Coastguard Worker 			  dwarf_errmsg (-1));
5683*7304104dSAndroid Build Coastguard Worker 		  return;
5684*7304104dSAndroid Build Coastguard Worker 		}
5685*7304104dSAndroid Build Coastguard Worker 
5686*7304104dSAndroid Build Coastguard Worker 	      /* This is the NUL byte at the end of the section.  */
5687*7304104dSAndroid Build Coastguard Worker 	      ++offset;
5688*7304104dSAndroid Build Coastguard Worker 	      break;
5689*7304104dSAndroid Build Coastguard Worker 	    }
5690*7304104dSAndroid Build Coastguard Worker 
5691*7304104dSAndroid Build Coastguard Worker 	  /* We know these calls can never fail.  */
5692*7304104dSAndroid Build Coastguard Worker 	  unsigned int code = dwarf_getabbrevcode (&abbrev);
5693*7304104dSAndroid Build Coastguard Worker 	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
5694*7304104dSAndroid Build Coastguard Worker 	  int has_children = dwarf_abbrevhaschildren (&abbrev);
5695*7304104dSAndroid Build Coastguard Worker 
5696*7304104dSAndroid Build Coastguard Worker 	  printf (_(" [%5u] offset: %" PRId64
5697*7304104dSAndroid Build Coastguard Worker 			   ", children: %s, tag: %s\n"),
5698*7304104dSAndroid Build Coastguard Worker 		  code, (int64_t) offset,
5699*7304104dSAndroid Build Coastguard Worker 		  has_children ? yes_str : no_str,
5700*7304104dSAndroid Build Coastguard Worker 		  dwarf_tag_name (tag));
5701*7304104dSAndroid Build Coastguard Worker 
5702*7304104dSAndroid Build Coastguard Worker 	  size_t cnt = 0;
5703*7304104dSAndroid Build Coastguard Worker 	  unsigned int name;
5704*7304104dSAndroid Build Coastguard Worker 	  unsigned int form;
5705*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Sword data;
5706*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off enoffset;
5707*7304104dSAndroid Build Coastguard Worker 	  while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
5708*7304104dSAndroid Build Coastguard Worker 					   &data, &enoffset) == 0)
5709*7304104dSAndroid Build Coastguard Worker 	    {
5710*7304104dSAndroid Build Coastguard Worker 	      printf ("          attr: %s, form: %s",
5711*7304104dSAndroid Build Coastguard Worker 		      dwarf_attr_name (name), dwarf_form_name (form));
5712*7304104dSAndroid Build Coastguard Worker 	      if (form == DW_FORM_implicit_const)
5713*7304104dSAndroid Build Coastguard Worker 		printf (" (%" PRId64 ")", data);
5714*7304104dSAndroid Build Coastguard Worker 	      printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
5715*7304104dSAndroid Build Coastguard Worker 	      ++cnt;
5716*7304104dSAndroid Build Coastguard Worker 	    }
5717*7304104dSAndroid Build Coastguard Worker 
5718*7304104dSAndroid Build Coastguard Worker 	  offset += length;
5719*7304104dSAndroid Build Coastguard Worker 	}
5720*7304104dSAndroid Build Coastguard Worker     }
5721*7304104dSAndroid Build Coastguard Worker }
5722*7304104dSAndroid Build Coastguard Worker 
5723*7304104dSAndroid Build Coastguard Worker 
5724*7304104dSAndroid Build Coastguard Worker static void
print_debug_addr_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)5725*7304104dSAndroid Build Coastguard Worker print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
5726*7304104dSAndroid Build Coastguard Worker 			  Ebl *ebl, GElf_Ehdr *ehdr,
5727*7304104dSAndroid Build Coastguard Worker 			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
5728*7304104dSAndroid Build Coastguard Worker {
5729*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_addr, scn);
5730*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
5731*7304104dSAndroid Build Coastguard Worker     return;
5732*7304104dSAndroid Build Coastguard Worker 
5733*7304104dSAndroid Build Coastguard Worker   printf (_("\
5734*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
5735*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
5736*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
5737*7304104dSAndroid Build Coastguard Worker 
5738*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_size == 0)
5739*7304104dSAndroid Build Coastguard Worker     return;
5740*7304104dSAndroid Build Coastguard Worker 
5741*7304104dSAndroid Build Coastguard Worker   size_t idx = 0;
5742*7304104dSAndroid Build Coastguard Worker   sort_listptr (&known_addrbases, "addr_base");
5743*7304104dSAndroid Build Coastguard Worker 
5744*7304104dSAndroid Build Coastguard Worker   const unsigned char *start = (const unsigned char *) data->d_buf;
5745*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = start;
5746*7304104dSAndroid Build Coastguard Worker   const unsigned char *readendp = ((const unsigned char *) data->d_buf
5747*7304104dSAndroid Build Coastguard Worker 				   + data->d_size);
5748*7304104dSAndroid Build Coastguard Worker 
5749*7304104dSAndroid Build Coastguard Worker   while (readp < readendp)
5750*7304104dSAndroid Build Coastguard Worker     {
5751*7304104dSAndroid Build Coastguard Worker       /* We cannot really know whether or not there is an header.  The
5752*7304104dSAndroid Build Coastguard Worker 	 DebugFission extension to DWARF4 doesn't add one.  The DWARF5
5753*7304104dSAndroid Build Coastguard Worker 	 .debug_addr variant does.  Whether or not we have an header,
5754*7304104dSAndroid Build Coastguard Worker 	 DW_AT_[GNU_]addr_base points at "index 0".  So if the current
5755*7304104dSAndroid Build Coastguard Worker 	 offset equals the CU addr_base then we can just start
5756*7304104dSAndroid Build Coastguard Worker 	 printing addresses.  If there is no CU with an exact match
5757*7304104dSAndroid Build Coastguard Worker 	 then we'll try to parse the header first.  */
5758*7304104dSAndroid Build Coastguard Worker       Dwarf_Off off = (Dwarf_Off) (readp
5759*7304104dSAndroid Build Coastguard Worker 				   - (const unsigned char *) data->d_buf);
5760*7304104dSAndroid Build Coastguard Worker 
5761*7304104dSAndroid Build Coastguard Worker       printf ("Table at offset %" PRIx64 " ", off);
5762*7304104dSAndroid Build Coastguard Worker 
5763*7304104dSAndroid Build Coastguard Worker       struct listptr *listptr = get_listptr (&known_addrbases, idx++);
5764*7304104dSAndroid Build Coastguard Worker       const unsigned char *next_unitp;
5765*7304104dSAndroid Build Coastguard Worker 
5766*7304104dSAndroid Build Coastguard Worker       uint64_t unit_length;
5767*7304104dSAndroid Build Coastguard Worker       uint16_t version;
5768*7304104dSAndroid Build Coastguard Worker       uint8_t address_size;
5769*7304104dSAndroid Build Coastguard Worker       uint8_t segment_size;
5770*7304104dSAndroid Build Coastguard Worker       if (listptr == NULL)
5771*7304104dSAndroid Build Coastguard Worker 	{
5772*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, "Warning: No CU references .debug_addr after %" PRIx64,
5773*7304104dSAndroid Build Coastguard Worker 		 off);
5774*7304104dSAndroid Build Coastguard Worker 
5775*7304104dSAndroid Build Coastguard Worker 	  /* We will have to assume it is just addresses to the end... */
5776*7304104dSAndroid Build Coastguard Worker 	  address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
5777*7304104dSAndroid Build Coastguard Worker 	  next_unitp = readendp;
5778*7304104dSAndroid Build Coastguard Worker 	  printf ("Unknown CU:\n");
5779*7304104dSAndroid Build Coastguard Worker 	}
5780*7304104dSAndroid Build Coastguard Worker       else
5781*7304104dSAndroid Build Coastguard Worker 	{
5782*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Die cudie;
5783*7304104dSAndroid Build Coastguard Worker 	  if (dwarf_cu_die (listptr->cu, &cudie,
5784*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL, NULL, NULL,
5785*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL) == NULL)
5786*7304104dSAndroid Build Coastguard Worker 	    printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
5787*7304104dSAndroid Build Coastguard Worker 	  else
5788*7304104dSAndroid Build Coastguard Worker 	    printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
5789*7304104dSAndroid Build Coastguard Worker 
5790*7304104dSAndroid Build Coastguard Worker 	  if (listptr->offset == off)
5791*7304104dSAndroid Build Coastguard Worker 	    {
5792*7304104dSAndroid Build Coastguard Worker 	      address_size = listptr_address_size (listptr);
5793*7304104dSAndroid Build Coastguard Worker 	      segment_size = 0;
5794*7304104dSAndroid Build Coastguard Worker 	      version = 4;
5795*7304104dSAndroid Build Coastguard Worker 
5796*7304104dSAndroid Build Coastguard Worker 	      /* The addresses start here, but where do they end?  */
5797*7304104dSAndroid Build Coastguard Worker 	      listptr = get_listptr (&known_addrbases, idx);
5798*7304104dSAndroid Build Coastguard Worker 	      if (listptr == NULL)
5799*7304104dSAndroid Build Coastguard Worker 		next_unitp = readendp;
5800*7304104dSAndroid Build Coastguard Worker 	      else if (listptr->cu->version < 5)
5801*7304104dSAndroid Build Coastguard Worker 		{
5802*7304104dSAndroid Build Coastguard Worker 		  next_unitp = start + listptr->offset;
5803*7304104dSAndroid Build Coastguard Worker 		  if (listptr->offset < off || listptr->offset > data->d_size)
5804*7304104dSAndroid Build Coastguard Worker 		    {
5805*7304104dSAndroid Build Coastguard Worker 		      error (0, 0,
5806*7304104dSAndroid Build Coastguard Worker 			     "Warning: Bad address base for next unit at %"
5807*7304104dSAndroid Build Coastguard Worker 			     PRIx64, off);
5808*7304104dSAndroid Build Coastguard Worker 		      next_unitp = readendp;
5809*7304104dSAndroid Build Coastguard Worker 		    }
5810*7304104dSAndroid Build Coastguard Worker 		}
5811*7304104dSAndroid Build Coastguard Worker 	      else
5812*7304104dSAndroid Build Coastguard Worker 		{
5813*7304104dSAndroid Build Coastguard Worker 		  /* Tricky, we don't have a header for this unit, but
5814*7304104dSAndroid Build Coastguard Worker 		     there is one for the next.  We will have to
5815*7304104dSAndroid Build Coastguard Worker 		     "guess" how big it is and subtract it from the
5816*7304104dSAndroid Build Coastguard Worker 		     offset (because that points after the header).  */
5817*7304104dSAndroid Build Coastguard Worker 		  unsigned int offset_size = listptr_offset_size (listptr);
5818*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Off next_off = (listptr->offset
5819*7304104dSAndroid Build Coastguard Worker 					- (offset_size == 4 ? 4 : 12) /* len */
5820*7304104dSAndroid Build Coastguard Worker 					- 2 /* version */
5821*7304104dSAndroid Build Coastguard Worker 					- 1 /* address size */
5822*7304104dSAndroid Build Coastguard Worker 					- 1); /* segment selector size */
5823*7304104dSAndroid Build Coastguard Worker 		  next_unitp = start + next_off;
5824*7304104dSAndroid Build Coastguard Worker 		  if (next_off < off || next_off > data->d_size)
5825*7304104dSAndroid Build Coastguard Worker 		    {
5826*7304104dSAndroid Build Coastguard Worker 		      error (0, 0,
5827*7304104dSAndroid Build Coastguard Worker 			     "Warning: Couldn't calculate .debug_addr "
5828*7304104dSAndroid Build Coastguard Worker 			     " unit length at %" PRIx64, off);
5829*7304104dSAndroid Build Coastguard Worker 		      next_unitp = readendp;
5830*7304104dSAndroid Build Coastguard Worker 		    }
5831*7304104dSAndroid Build Coastguard Worker 		}
5832*7304104dSAndroid Build Coastguard Worker 	      unit_length = (uint64_t) (next_unitp - readp);
5833*7304104dSAndroid Build Coastguard Worker 
5834*7304104dSAndroid Build Coastguard Worker 	      /* Pretend we have a header.  */
5835*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
5836*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Length:         %8" PRIu64 "\n"),
5837*7304104dSAndroid Build Coastguard Worker 		      unit_length);
5838*7304104dSAndroid Build Coastguard Worker 	      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
5839*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Address size:   %8" PRIu64 "\n"),
5840*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) address_size);
5841*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Segment size:   %8" PRIu64 "\n"),
5842*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) segment_size);
5843*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
5844*7304104dSAndroid Build Coastguard Worker 	    }
5845*7304104dSAndroid Build Coastguard Worker 	  else
5846*7304104dSAndroid Build Coastguard Worker 	    {
5847*7304104dSAndroid Build Coastguard Worker 	      /* OK, we have to parse an header first.  */
5848*7304104dSAndroid Build Coastguard Worker 	      unit_length = read_4ubyte_unaligned_inc (dbg, readp);
5849*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (unit_length == 0xffffffff))
5850*7304104dSAndroid Build Coastguard Worker 		{
5851*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (readp > readendp - 8))
5852*7304104dSAndroid Build Coastguard Worker 		    {
5853*7304104dSAndroid Build Coastguard Worker 		    invalid_data:
5854*7304104dSAndroid Build Coastguard Worker 		      error (0, 0, "Invalid data");
5855*7304104dSAndroid Build Coastguard Worker 		      return;
5856*7304104dSAndroid Build Coastguard Worker 		    }
5857*7304104dSAndroid Build Coastguard Worker 		  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
5858*7304104dSAndroid Build Coastguard Worker 		}
5859*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
5860*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Length:         %8" PRIu64 "\n"),
5861*7304104dSAndroid Build Coastguard Worker 		      unit_length);
5862*7304104dSAndroid Build Coastguard Worker 
5863*7304104dSAndroid Build Coastguard Worker 	      /* We need at least 2-bytes (version) + 1-byte
5864*7304104dSAndroid Build Coastguard Worker 		 (addr_size) + 1-byte (segment_size) = 4 bytes to
5865*7304104dSAndroid Build Coastguard Worker 		 complete the header.  And this unit cannot go beyond
5866*7304104dSAndroid Build Coastguard Worker 		 the section data.  */
5867*7304104dSAndroid Build Coastguard Worker 	      if (readp > readendp - 4
5868*7304104dSAndroid Build Coastguard Worker 		  || unit_length < 4
5869*7304104dSAndroid Build Coastguard Worker 		  || unit_length > (uint64_t) (readendp - readp))
5870*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
5871*7304104dSAndroid Build Coastguard Worker 
5872*7304104dSAndroid Build Coastguard Worker 	      next_unitp = readp + unit_length;
5873*7304104dSAndroid Build Coastguard Worker 
5874*7304104dSAndroid Build Coastguard Worker 	      version = read_2ubyte_unaligned_inc (dbg, readp);
5875*7304104dSAndroid Build Coastguard Worker 	      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
5876*7304104dSAndroid Build Coastguard Worker 
5877*7304104dSAndroid Build Coastguard Worker 	      if (version != 5)
5878*7304104dSAndroid Build Coastguard Worker 		{
5879*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("Unknown version"));
5880*7304104dSAndroid Build Coastguard Worker 		  goto next_unit;
5881*7304104dSAndroid Build Coastguard Worker 		}
5882*7304104dSAndroid Build Coastguard Worker 
5883*7304104dSAndroid Build Coastguard Worker 	      address_size = *readp++;
5884*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Address size:   %8" PRIu64 "\n"),
5885*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) address_size);
5886*7304104dSAndroid Build Coastguard Worker 
5887*7304104dSAndroid Build Coastguard Worker 	      if (address_size != 4 && address_size != 8)
5888*7304104dSAndroid Build Coastguard Worker 		{
5889*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("unsupported address size"));
5890*7304104dSAndroid Build Coastguard Worker 		  goto next_unit;
5891*7304104dSAndroid Build Coastguard Worker 		}
5892*7304104dSAndroid Build Coastguard Worker 
5893*7304104dSAndroid Build Coastguard Worker 	      segment_size = *readp++;
5894*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Segment size:   %8" PRIu64 "\n"),
5895*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) segment_size);
5896*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
5897*7304104dSAndroid Build Coastguard Worker 
5898*7304104dSAndroid Build Coastguard Worker 	      if (segment_size != 0)
5899*7304104dSAndroid Build Coastguard Worker 		{
5900*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("unsupported segment size"));
5901*7304104dSAndroid Build Coastguard Worker 		  goto next_unit;
5902*7304104dSAndroid Build Coastguard Worker 		}
5903*7304104dSAndroid Build Coastguard Worker 
5904*7304104dSAndroid Build Coastguard Worker 	      if (listptr->offset != (Dwarf_Off) (readp - start))
5905*7304104dSAndroid Build Coastguard Worker 		{
5906*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, "Address index doesn't start after header");
5907*7304104dSAndroid Build Coastguard Worker 		  goto next_unit;
5908*7304104dSAndroid Build Coastguard Worker 		}
5909*7304104dSAndroid Build Coastguard Worker 	    }
5910*7304104dSAndroid Build Coastguard Worker 	}
5911*7304104dSAndroid Build Coastguard Worker 
5912*7304104dSAndroid Build Coastguard Worker       int digits = 1;
5913*7304104dSAndroid Build Coastguard Worker       size_t addresses = (next_unitp - readp) / address_size;
5914*7304104dSAndroid Build Coastguard Worker       while (addresses >= 10)
5915*7304104dSAndroid Build Coastguard Worker 	{
5916*7304104dSAndroid Build Coastguard Worker 	  ++digits;
5917*7304104dSAndroid Build Coastguard Worker 	  addresses /= 10;
5918*7304104dSAndroid Build Coastguard Worker 	}
5919*7304104dSAndroid Build Coastguard Worker 
5920*7304104dSAndroid Build Coastguard Worker       unsigned int uidx = 0;
5921*7304104dSAndroid Build Coastguard Worker       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
5922*7304104dSAndroid Build Coastguard Worker       printf (" Addresses start at offset 0x%zx:\n", index_offset);
5923*7304104dSAndroid Build Coastguard Worker       while (readp <= next_unitp - address_size)
5924*7304104dSAndroid Build Coastguard Worker 	{
5925*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg,
5926*7304104dSAndroid Build Coastguard Worker 						     readp);
5927*7304104dSAndroid Build Coastguard Worker 	  printf (" [%*u] ", digits, uidx++);
5928*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size, addr, addr);
5929*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
5930*7304104dSAndroid Build Coastguard Worker 	}
5931*7304104dSAndroid Build Coastguard Worker       printf ("\n");
5932*7304104dSAndroid Build Coastguard Worker 
5933*7304104dSAndroid Build Coastguard Worker       if (readp != next_unitp)
5934*7304104dSAndroid Build Coastguard Worker 	error (0, 0, "extra %zd bytes at end of unit",
5935*7304104dSAndroid Build Coastguard Worker 	       (size_t) (next_unitp - readp));
5936*7304104dSAndroid Build Coastguard Worker 
5937*7304104dSAndroid Build Coastguard Worker     next_unit:
5938*7304104dSAndroid Build Coastguard Worker       readp = next_unitp;
5939*7304104dSAndroid Build Coastguard Worker     }
5940*7304104dSAndroid Build Coastguard Worker }
5941*7304104dSAndroid Build Coastguard Worker 
5942*7304104dSAndroid Build Coastguard Worker /* Print content of DWARF .debug_aranges section.  We fortunately do
5943*7304104dSAndroid Build Coastguard Worker    not have to know a bit about the structure of the section, libdwarf
5944*7304104dSAndroid Build Coastguard Worker    takes care of it.  */
5945*7304104dSAndroid Build Coastguard Worker static void
print_decoded_aranges_section(Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)5946*7304104dSAndroid Build Coastguard Worker print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
5947*7304104dSAndroid Build Coastguard Worker 			       GElf_Shdr *shdr, Dwarf *dbg)
5948*7304104dSAndroid Build Coastguard Worker {
5949*7304104dSAndroid Build Coastguard Worker   Dwarf_Aranges *aranges;
5950*7304104dSAndroid Build Coastguard Worker   size_t cnt;
5951*7304104dSAndroid Build Coastguard Worker   if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
5952*7304104dSAndroid Build Coastguard Worker     {
5953*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get .debug_aranges content: %s"),
5954*7304104dSAndroid Build Coastguard Worker 	     dwarf_errmsg (-1));
5955*7304104dSAndroid Build Coastguard Worker       return;
5956*7304104dSAndroid Build Coastguard Worker     }
5957*7304104dSAndroid Build Coastguard Worker 
5958*7304104dSAndroid Build Coastguard Worker   GElf_Shdr glink_mem;
5959*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *glink;
5960*7304104dSAndroid Build Coastguard Worker   glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
5961*7304104dSAndroid Build Coastguard Worker   if (glink == NULL)
5962*7304104dSAndroid Build Coastguard Worker     {
5963*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid sh_link value in section %zu"),
5964*7304104dSAndroid Build Coastguard Worker 	     elf_ndxscn (scn));
5965*7304104dSAndroid Build Coastguard Worker       return;
5966*7304104dSAndroid Build Coastguard Worker     }
5967*7304104dSAndroid Build Coastguard Worker 
5968*7304104dSAndroid Build Coastguard Worker   printf (ngettext ("\
5969*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
5970*7304104dSAndroid Build Coastguard Worker 		    "\
5971*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
5972*7304104dSAndroid Build Coastguard Worker 		    cnt),
5973*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
5974*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset, cnt);
5975*7304104dSAndroid Build Coastguard Worker 
5976*7304104dSAndroid Build Coastguard Worker   /* Compute floor(log16(cnt)).  */
5977*7304104dSAndroid Build Coastguard Worker   size_t tmp = cnt;
5978*7304104dSAndroid Build Coastguard Worker   int digits = 1;
5979*7304104dSAndroid Build Coastguard Worker   while (tmp >= 16)
5980*7304104dSAndroid Build Coastguard Worker     {
5981*7304104dSAndroid Build Coastguard Worker       ++digits;
5982*7304104dSAndroid Build Coastguard Worker       tmp >>= 4;
5983*7304104dSAndroid Build Coastguard Worker     }
5984*7304104dSAndroid Build Coastguard Worker 
5985*7304104dSAndroid Build Coastguard Worker   for (size_t n = 0; n < cnt; ++n)
5986*7304104dSAndroid Build Coastguard Worker     {
5987*7304104dSAndroid Build Coastguard Worker       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
5988*7304104dSAndroid Build Coastguard Worker       if (unlikely (runp == NULL))
5989*7304104dSAndroid Build Coastguard Worker 	{
5990*7304104dSAndroid Build Coastguard Worker 	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
5991*7304104dSAndroid Build Coastguard Worker 	  return;
5992*7304104dSAndroid Build Coastguard Worker 	}
5993*7304104dSAndroid Build Coastguard Worker 
5994*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr start;
5995*7304104dSAndroid Build Coastguard Worker       Dwarf_Word length;
5996*7304104dSAndroid Build Coastguard Worker       Dwarf_Off offset;
5997*7304104dSAndroid Build Coastguard Worker 
5998*7304104dSAndroid Build Coastguard Worker       if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
5999*7304104dSAndroid Build Coastguard Worker 	printf (_(" [%*zu] ???\n"), digits, n);
6000*7304104dSAndroid Build Coastguard Worker       else
6001*7304104dSAndroid Build Coastguard Worker 	printf (_(" [%*zu] start: %0#*" PRIx64
6002*7304104dSAndroid Build Coastguard Worker 			 ", length: %5" PRIu64 ", CU DIE offset: %6"
6003*7304104dSAndroid Build Coastguard Worker 			 PRId64 "\n"),
6004*7304104dSAndroid Build Coastguard Worker 		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
6005*7304104dSAndroid Build Coastguard Worker 		(uint64_t) start, (uint64_t) length, (int64_t) offset);
6006*7304104dSAndroid Build Coastguard Worker     }
6007*7304104dSAndroid Build Coastguard Worker }
6008*7304104dSAndroid Build Coastguard Worker 
6009*7304104dSAndroid Build Coastguard Worker 
6010*7304104dSAndroid Build Coastguard Worker /* Print content of DWARF .debug_aranges section.  */
6011*7304104dSAndroid Build Coastguard Worker static void
print_debug_aranges_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)6012*7304104dSAndroid Build Coastguard Worker print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
6013*7304104dSAndroid Build Coastguard Worker 			     Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
6014*7304104dSAndroid Build Coastguard Worker 			     GElf_Shdr *shdr, Dwarf *dbg)
6015*7304104dSAndroid Build Coastguard Worker {
6016*7304104dSAndroid Build Coastguard Worker   if (decodedaranges)
6017*7304104dSAndroid Build Coastguard Worker     {
6018*7304104dSAndroid Build Coastguard Worker       print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
6019*7304104dSAndroid Build Coastguard Worker       return;
6020*7304104dSAndroid Build Coastguard Worker     }
6021*7304104dSAndroid Build Coastguard Worker 
6022*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_aranges, scn);
6023*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
6024*7304104dSAndroid Build Coastguard Worker     return;
6025*7304104dSAndroid Build Coastguard Worker 
6026*7304104dSAndroid Build Coastguard Worker   printf (_("\
6027*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6028*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
6029*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
6030*7304104dSAndroid Build Coastguard Worker 
6031*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = data->d_buf;
6032*7304104dSAndroid Build Coastguard Worker   const unsigned char *readendp = readp + data->d_size;
6033*7304104dSAndroid Build Coastguard Worker 
6034*7304104dSAndroid Build Coastguard Worker   while (readp < readendp)
6035*7304104dSAndroid Build Coastguard Worker     {
6036*7304104dSAndroid Build Coastguard Worker       const unsigned char *hdrstart = readp;
6037*7304104dSAndroid Build Coastguard Worker       size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
6038*7304104dSAndroid Build Coastguard Worker 
6039*7304104dSAndroid Build Coastguard Worker       printf (_("\nTable at offset %zu:\n"), start_offset);
6040*7304104dSAndroid Build Coastguard Worker       if (readp + 4 > readendp)
6041*7304104dSAndroid Build Coastguard Worker 	{
6042*7304104dSAndroid Build Coastguard Worker 	invalid_data:
6043*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("invalid data in section [%zu] '%s'"),
6044*7304104dSAndroid Build Coastguard Worker 		 elf_ndxscn (scn), section_name (ebl, shdr));
6045*7304104dSAndroid Build Coastguard Worker 	  return;
6046*7304104dSAndroid Build Coastguard Worker 	}
6047*7304104dSAndroid Build Coastguard Worker 
6048*7304104dSAndroid Build Coastguard Worker       Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
6049*7304104dSAndroid Build Coastguard Worker       unsigned int length_bytes = 4;
6050*7304104dSAndroid Build Coastguard Worker       if (length == DWARF3_LENGTH_64_BIT)
6051*7304104dSAndroid Build Coastguard Worker 	{
6052*7304104dSAndroid Build Coastguard Worker 	  if (readp + 8 > readendp)
6053*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
6054*7304104dSAndroid Build Coastguard Worker 	  length = read_8ubyte_unaligned_inc (dbg, readp);
6055*7304104dSAndroid Build Coastguard Worker 	  length_bytes = 8;
6056*7304104dSAndroid Build Coastguard Worker 	}
6057*7304104dSAndroid Build Coastguard Worker 
6058*7304104dSAndroid Build Coastguard Worker       const unsigned char *nexthdr = readp + length;
6059*7304104dSAndroid Build Coastguard Worker       printf (_("\n Length:        %6" PRIu64 "\n"),
6060*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) length);
6061*7304104dSAndroid Build Coastguard Worker 
6062*7304104dSAndroid Build Coastguard Worker       if (unlikely (length > (size_t) (readendp - readp)))
6063*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
6064*7304104dSAndroid Build Coastguard Worker 
6065*7304104dSAndroid Build Coastguard Worker       if (length == 0)
6066*7304104dSAndroid Build Coastguard Worker 	continue;
6067*7304104dSAndroid Build Coastguard Worker 
6068*7304104dSAndroid Build Coastguard Worker       if (readp + 2 > readendp)
6069*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
6070*7304104dSAndroid Build Coastguard Worker       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
6071*7304104dSAndroid Build Coastguard Worker       printf (_(" DWARF version: %6" PRIuFAST16 "\n"),
6072*7304104dSAndroid Build Coastguard Worker 	      version);
6073*7304104dSAndroid Build Coastguard Worker       if (version != 2)
6074*7304104dSAndroid Build Coastguard Worker 	{
6075*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("unsupported aranges version"));
6076*7304104dSAndroid Build Coastguard Worker 	  goto next_table;
6077*7304104dSAndroid Build Coastguard Worker 	}
6078*7304104dSAndroid Build Coastguard Worker 
6079*7304104dSAndroid Build Coastguard Worker       Dwarf_Word offset;
6080*7304104dSAndroid Build Coastguard Worker       if (readp + length_bytes > readendp)
6081*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
6082*7304104dSAndroid Build Coastguard Worker       if (length_bytes == 8)
6083*7304104dSAndroid Build Coastguard Worker 	offset = read_8ubyte_unaligned_inc (dbg, readp);
6084*7304104dSAndroid Build Coastguard Worker       else
6085*7304104dSAndroid Build Coastguard Worker 	offset = read_4ubyte_unaligned_inc (dbg, readp);
6086*7304104dSAndroid Build Coastguard Worker       printf (_(" CU offset:     %6" PRIx64 "\n"),
6087*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) offset);
6088*7304104dSAndroid Build Coastguard Worker 
6089*7304104dSAndroid Build Coastguard Worker       if (readp + 1 > readendp)
6090*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
6091*7304104dSAndroid Build Coastguard Worker       unsigned int address_size = *readp++;
6092*7304104dSAndroid Build Coastguard Worker       printf (_(" Address size:  %6" PRIu64 "\n"),
6093*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) address_size);
6094*7304104dSAndroid Build Coastguard Worker       if (address_size != 4 && address_size != 8)
6095*7304104dSAndroid Build Coastguard Worker 	{
6096*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("unsupported address size"));
6097*7304104dSAndroid Build Coastguard Worker 	  goto next_table;
6098*7304104dSAndroid Build Coastguard Worker 	}
6099*7304104dSAndroid Build Coastguard Worker 
6100*7304104dSAndroid Build Coastguard Worker       if (readp + 1 > readendp)
6101*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
6102*7304104dSAndroid Build Coastguard Worker       unsigned int segment_size = *readp++;
6103*7304104dSAndroid Build Coastguard Worker       printf (_(" Segment size:  %6" PRIu64 "\n\n"),
6104*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) segment_size);
6105*7304104dSAndroid Build Coastguard Worker       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
6106*7304104dSAndroid Build Coastguard Worker 	{
6107*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("unsupported segment size"));
6108*7304104dSAndroid Build Coastguard Worker 	  goto next_table;
6109*7304104dSAndroid Build Coastguard Worker 	}
6110*7304104dSAndroid Build Coastguard Worker 
6111*7304104dSAndroid Build Coastguard Worker       /* Round the address to the next multiple of 2*address_size.  */
6112*7304104dSAndroid Build Coastguard Worker       readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
6113*7304104dSAndroid Build Coastguard Worker 		% (2 * address_size));
6114*7304104dSAndroid Build Coastguard Worker 
6115*7304104dSAndroid Build Coastguard Worker       while (readp < nexthdr)
6116*7304104dSAndroid Build Coastguard Worker 	{
6117*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word range_address;
6118*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word range_length;
6119*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word segment = 0;
6120*7304104dSAndroid Build Coastguard Worker 	  if (readp + 2 * address_size + segment_size > readendp)
6121*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
6122*7304104dSAndroid Build Coastguard Worker 	  if (address_size == 4)
6123*7304104dSAndroid Build Coastguard Worker 	    {
6124*7304104dSAndroid Build Coastguard Worker 	      range_address = read_4ubyte_unaligned_inc (dbg, readp);
6125*7304104dSAndroid Build Coastguard Worker 	      range_length = read_4ubyte_unaligned_inc (dbg, readp);
6126*7304104dSAndroid Build Coastguard Worker 	    }
6127*7304104dSAndroid Build Coastguard Worker 	  else
6128*7304104dSAndroid Build Coastguard Worker 	    {
6129*7304104dSAndroid Build Coastguard Worker 	      range_address = read_8ubyte_unaligned_inc (dbg, readp);
6130*7304104dSAndroid Build Coastguard Worker 	      range_length = read_8ubyte_unaligned_inc (dbg, readp);
6131*7304104dSAndroid Build Coastguard Worker 	    }
6132*7304104dSAndroid Build Coastguard Worker 
6133*7304104dSAndroid Build Coastguard Worker 	  if (segment_size == 4)
6134*7304104dSAndroid Build Coastguard Worker 	    segment = read_4ubyte_unaligned_inc (dbg, readp);
6135*7304104dSAndroid Build Coastguard Worker 	  else if (segment_size == 8)
6136*7304104dSAndroid Build Coastguard Worker 	    segment = read_8ubyte_unaligned_inc (dbg, readp);
6137*7304104dSAndroid Build Coastguard Worker 
6138*7304104dSAndroid Build Coastguard Worker 	  if (range_address == 0 && range_length == 0 && segment == 0)
6139*7304104dSAndroid Build Coastguard Worker 	    break;
6140*7304104dSAndroid Build Coastguard Worker 
6141*7304104dSAndroid Build Coastguard Worker 	  printf ("   ");
6142*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size, range_address,
6143*7304104dSAndroid Build Coastguard Worker 			    range_address);
6144*7304104dSAndroid Build Coastguard Worker 	  printf ("..");
6145*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size,
6146*7304104dSAndroid Build Coastguard Worker 			    range_address + range_length - 1,
6147*7304104dSAndroid Build Coastguard Worker 			    range_length);
6148*7304104dSAndroid Build Coastguard Worker 	  if (segment_size != 0)
6149*7304104dSAndroid Build Coastguard Worker 	    printf (" (%" PRIx64 ")\n", (uint64_t) segment);
6150*7304104dSAndroid Build Coastguard Worker 	  else
6151*7304104dSAndroid Build Coastguard Worker 	    printf ("\n");
6152*7304104dSAndroid Build Coastguard Worker 	}
6153*7304104dSAndroid Build Coastguard Worker 
6154*7304104dSAndroid Build Coastguard Worker     next_table:
6155*7304104dSAndroid Build Coastguard Worker       if (readp != nexthdr)
6156*7304104dSAndroid Build Coastguard Worker 	{
6157*7304104dSAndroid Build Coastguard Worker 	  size_t padding = nexthdr - readp;
6158*7304104dSAndroid Build Coastguard Worker 	  printf (_("   %zu padding bytes\n"), padding);
6159*7304104dSAndroid Build Coastguard Worker 	  readp = nexthdr;
6160*7304104dSAndroid Build Coastguard Worker 	}
6161*7304104dSAndroid Build Coastguard Worker     }
6162*7304104dSAndroid Build Coastguard Worker }
6163*7304104dSAndroid Build Coastguard Worker 
6164*7304104dSAndroid Build Coastguard Worker 
6165*7304104dSAndroid Build Coastguard Worker static bool is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu);
6166*7304104dSAndroid Build Coastguard Worker 
6167*7304104dSAndroid Build Coastguard Worker /* Returns true and sets cu and cu_base if the given Dwarf is a split
6168*7304104dSAndroid Build Coastguard Worker    DWARF (.dwo) file.  */
6169*7304104dSAndroid Build Coastguard Worker static bool
split_dwarf_cu_base(Dwarf * dbg,Dwarf_CU ** cu,Dwarf_Addr * cu_base)6170*7304104dSAndroid Build Coastguard Worker split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
6171*7304104dSAndroid Build Coastguard Worker {
6172*7304104dSAndroid Build Coastguard Worker   uint64_t id;
6173*7304104dSAndroid Build Coastguard Worker   if (is_split_dwarf (dbg, &id, cu))
6174*7304104dSAndroid Build Coastguard Worker     {
6175*7304104dSAndroid Build Coastguard Worker       Dwarf_Die cudie;
6176*7304104dSAndroid Build Coastguard Worker       if (dwarf_cu_info (*cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL) == 0)
6177*7304104dSAndroid Build Coastguard Worker 	{
6178*7304104dSAndroid Build Coastguard Worker 	  *cu_base = cudie_base (&cudie);
6179*7304104dSAndroid Build Coastguard Worker 	  return true;
6180*7304104dSAndroid Build Coastguard Worker 	}
6181*7304104dSAndroid Build Coastguard Worker     }
6182*7304104dSAndroid Build Coastguard Worker   return false;
6183*7304104dSAndroid Build Coastguard Worker }
6184*7304104dSAndroid Build Coastguard Worker 
6185*7304104dSAndroid Build Coastguard Worker /* Print content of DWARF .debug_rnglists section.  */
6186*7304104dSAndroid Build Coastguard Worker static void
print_debug_rnglists_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)6187*7304104dSAndroid Build Coastguard Worker print_debug_rnglists_section (Dwfl_Module *dwflmod,
6188*7304104dSAndroid Build Coastguard Worker 			      Ebl *ebl,
6189*7304104dSAndroid Build Coastguard Worker 			      GElf_Ehdr *ehdr __attribute__ ((unused)),
6190*7304104dSAndroid Build Coastguard Worker 			      Elf_Scn *scn, GElf_Shdr *shdr,
6191*7304104dSAndroid Build Coastguard Worker 			      Dwarf *dbg __attribute__((unused)))
6192*7304104dSAndroid Build Coastguard Worker {
6193*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_rnglists, scn);
6194*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
6195*7304104dSAndroid Build Coastguard Worker     return;
6196*7304104dSAndroid Build Coastguard Worker 
6197*7304104dSAndroid Build Coastguard Worker   printf (_("\
6198*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6199*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
6200*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
6201*7304104dSAndroid Build Coastguard Worker 
6202*7304104dSAndroid Build Coastguard Worker   /* For the listptr to get the base address/CU.  */
6203*7304104dSAndroid Build Coastguard Worker   sort_listptr (&known_rnglistptr, "rnglistptr");
6204*7304104dSAndroid Build Coastguard Worker   size_t listptr_idx = 0;
6205*7304104dSAndroid Build Coastguard Worker 
6206*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = data->d_buf;
6207*7304104dSAndroid Build Coastguard Worker   const unsigned char *const dataend = ((unsigned char *) data->d_buf
6208*7304104dSAndroid Build Coastguard Worker 					+ data->d_size);
6209*7304104dSAndroid Build Coastguard Worker   while (readp < dataend)
6210*7304104dSAndroid Build Coastguard Worker     {
6211*7304104dSAndroid Build Coastguard Worker       if (unlikely (readp > dataend - 4))
6212*7304104dSAndroid Build Coastguard Worker 	{
6213*7304104dSAndroid Build Coastguard Worker 	invalid_data:
6214*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("invalid data in section [%zu] '%s'"),
6215*7304104dSAndroid Build Coastguard Worker 		 elf_ndxscn (scn), section_name (ebl, shdr));
6216*7304104dSAndroid Build Coastguard Worker 	  return;
6217*7304104dSAndroid Build Coastguard Worker 	}
6218*7304104dSAndroid Build Coastguard Worker 
6219*7304104dSAndroid Build Coastguard Worker       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6220*7304104dSAndroid Build Coastguard Worker       printf (_("Table at Offset 0x%" PRIx64 ":\n\n"),
6221*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) offset);
6222*7304104dSAndroid Build Coastguard Worker 
6223*7304104dSAndroid Build Coastguard Worker       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
6224*7304104dSAndroid Build Coastguard Worker       unsigned int offset_size = 4;
6225*7304104dSAndroid Build Coastguard Worker       if (unlikely (unit_length == 0xffffffff))
6226*7304104dSAndroid Build Coastguard Worker 	{
6227*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (readp > dataend - 8))
6228*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
6229*7304104dSAndroid Build Coastguard Worker 
6230*7304104dSAndroid Build Coastguard Worker 	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
6231*7304104dSAndroid Build Coastguard Worker 	  offset_size = 8;
6232*7304104dSAndroid Build Coastguard Worker 	}
6233*7304104dSAndroid Build Coastguard Worker       printf (_(" Length:         %8" PRIu64 "\n"), unit_length);
6234*7304104dSAndroid Build Coastguard Worker 
6235*7304104dSAndroid Build Coastguard Worker       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
6236*7304104dSAndroid Build Coastguard Worker 	 bytes to complete the header.  And this unit cannot go beyond
6237*7304104dSAndroid Build Coastguard Worker 	 the section data.  */
6238*7304104dSAndroid Build Coastguard Worker       if (readp > dataend - 8
6239*7304104dSAndroid Build Coastguard Worker 	  || unit_length < 8
6240*7304104dSAndroid Build Coastguard Worker 	  || unit_length > (uint64_t) (dataend - readp))
6241*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
6242*7304104dSAndroid Build Coastguard Worker 
6243*7304104dSAndroid Build Coastguard Worker       const unsigned char *nexthdr = readp + unit_length;
6244*7304104dSAndroid Build Coastguard Worker 
6245*7304104dSAndroid Build Coastguard Worker       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
6246*7304104dSAndroid Build Coastguard Worker       printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
6247*7304104dSAndroid Build Coastguard Worker 
6248*7304104dSAndroid Build Coastguard Worker       if (version != 5)
6249*7304104dSAndroid Build Coastguard Worker 	{
6250*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("Unknown version"));
6251*7304104dSAndroid Build Coastguard Worker 	  goto next_table;
6252*7304104dSAndroid Build Coastguard Worker 	}
6253*7304104dSAndroid Build Coastguard Worker 
6254*7304104dSAndroid Build Coastguard Worker       uint8_t address_size = *readp++;
6255*7304104dSAndroid Build Coastguard Worker       printf (_(" Address size:   %8" PRIu64 "\n"),
6256*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) address_size);
6257*7304104dSAndroid Build Coastguard Worker 
6258*7304104dSAndroid Build Coastguard Worker       if (address_size != 4 && address_size != 8)
6259*7304104dSAndroid Build Coastguard Worker 	{
6260*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("unsupported address size"));
6261*7304104dSAndroid Build Coastguard Worker 	  goto next_table;
6262*7304104dSAndroid Build Coastguard Worker 	}
6263*7304104dSAndroid Build Coastguard Worker 
6264*7304104dSAndroid Build Coastguard Worker       uint8_t segment_size = *readp++;
6265*7304104dSAndroid Build Coastguard Worker       printf (_(" Segment size:   %8" PRIu64 "\n"),
6266*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) segment_size);
6267*7304104dSAndroid Build Coastguard Worker 
6268*7304104dSAndroid Build Coastguard Worker       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
6269*7304104dSAndroid Build Coastguard Worker         {
6270*7304104dSAndroid Build Coastguard Worker           error (0, 0, _("unsupported segment size"));
6271*7304104dSAndroid Build Coastguard Worker           goto next_table;
6272*7304104dSAndroid Build Coastguard Worker         }
6273*7304104dSAndroid Build Coastguard Worker 
6274*7304104dSAndroid Build Coastguard Worker       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
6275*7304104dSAndroid Build Coastguard Worker       printf (_(" Offset entries: %8" PRIu64 "\n"),
6276*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) offset_entry_count);
6277*7304104dSAndroid Build Coastguard Worker 
6278*7304104dSAndroid Build Coastguard Worker       /* We need the CU that uses this unit to get the initial base address. */
6279*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr cu_base = 0;
6280*7304104dSAndroid Build Coastguard Worker       struct Dwarf_CU *cu = NULL;
6281*7304104dSAndroid Build Coastguard Worker       if (listptr_cu (&known_rnglistptr, &listptr_idx,
6282*7304104dSAndroid Build Coastguard Worker 		      (Dwarf_Off) offset,
6283*7304104dSAndroid Build Coastguard Worker 		      (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
6284*7304104dSAndroid Build Coastguard Worker 		      &cu_base, &cu)
6285*7304104dSAndroid Build Coastguard Worker 	  || split_dwarf_cu_base (dbg, &cu, &cu_base))
6286*7304104dSAndroid Build Coastguard Worker 	{
6287*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Die cudie;
6288*7304104dSAndroid Build Coastguard Worker 	  if (dwarf_cu_die (cu, &cudie,
6289*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL, NULL, NULL,
6290*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL) == NULL)
6291*7304104dSAndroid Build Coastguard Worker 	    printf (_(" Unknown CU base: "));
6292*7304104dSAndroid Build Coastguard Worker 	  else
6293*7304104dSAndroid Build Coastguard Worker 	    printf (_(" CU [%6" PRIx64 "] base: "),
6294*7304104dSAndroid Build Coastguard Worker 		    dwarf_dieoffset (&cudie));
6295*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
6296*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
6297*7304104dSAndroid Build Coastguard Worker 	}
6298*7304104dSAndroid Build Coastguard Worker       else
6299*7304104dSAndroid Build Coastguard Worker 	printf (_(" Not associated with a CU.\n"));
6300*7304104dSAndroid Build Coastguard Worker 
6301*7304104dSAndroid Build Coastguard Worker       printf ("\n");
6302*7304104dSAndroid Build Coastguard Worker 
6303*7304104dSAndroid Build Coastguard Worker       const unsigned char *offset_array_start = readp;
6304*7304104dSAndroid Build Coastguard Worker       if (offset_entry_count > 0)
6305*7304104dSAndroid Build Coastguard Worker 	{
6306*7304104dSAndroid Build Coastguard Worker 	  uint64_t max_entries = (unit_length - 8) / offset_size;
6307*7304104dSAndroid Build Coastguard Worker 	  if (offset_entry_count > max_entries)
6308*7304104dSAndroid Build Coastguard Worker 	    {
6309*7304104dSAndroid Build Coastguard Worker 	      error (0, 0,
6310*7304104dSAndroid Build Coastguard Worker 		     _("too many offset entries for unit length"));
6311*7304104dSAndroid Build Coastguard Worker 	      offset_entry_count = max_entries;
6312*7304104dSAndroid Build Coastguard Worker 	    }
6313*7304104dSAndroid Build Coastguard Worker 
6314*7304104dSAndroid Build Coastguard Worker 	  printf (_("  Offsets starting at 0x%" PRIx64 ":\n"),
6315*7304104dSAndroid Build Coastguard Worker 		  (uint64_t) (offset_array_start
6316*7304104dSAndroid Build Coastguard Worker 			      - (unsigned char *) data->d_buf));
6317*7304104dSAndroid Build Coastguard Worker 	  for (uint32_t idx = 0; idx < offset_entry_count; idx++)
6318*7304104dSAndroid Build Coastguard Worker 	    {
6319*7304104dSAndroid Build Coastguard Worker 	      printf ("   [%6" PRIu32 "] ", idx);
6320*7304104dSAndroid Build Coastguard Worker 	      if (offset_size == 4)
6321*7304104dSAndroid Build Coastguard Worker 		{
6322*7304104dSAndroid Build Coastguard Worker 		  uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
6323*7304104dSAndroid Build Coastguard Worker 		  printf ("0x%" PRIx32 "\n", off);
6324*7304104dSAndroid Build Coastguard Worker 		}
6325*7304104dSAndroid Build Coastguard Worker 	      else
6326*7304104dSAndroid Build Coastguard Worker 		{
6327*7304104dSAndroid Build Coastguard Worker 		  uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
6328*7304104dSAndroid Build Coastguard Worker 		  printf ("0x%" PRIx64 "\n", off);
6329*7304104dSAndroid Build Coastguard Worker 		}
6330*7304104dSAndroid Build Coastguard Worker 	    }
6331*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
6332*7304104dSAndroid Build Coastguard Worker 	}
6333*7304104dSAndroid Build Coastguard Worker 
6334*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr base = cu_base;
6335*7304104dSAndroid Build Coastguard Worker       bool start_of_list = true;
6336*7304104dSAndroid Build Coastguard Worker       while (readp < nexthdr)
6337*7304104dSAndroid Build Coastguard Worker 	{
6338*7304104dSAndroid Build Coastguard Worker 	  uint8_t kind = *readp++;
6339*7304104dSAndroid Build Coastguard Worker 	  uint64_t op1, op2;
6340*7304104dSAndroid Build Coastguard Worker 
6341*7304104dSAndroid Build Coastguard Worker 	  /* Skip padding.  */
6342*7304104dSAndroid Build Coastguard Worker 	  if (start_of_list && kind == DW_RLE_end_of_list)
6343*7304104dSAndroid Build Coastguard Worker 	    continue;
6344*7304104dSAndroid Build Coastguard Worker 
6345*7304104dSAndroid Build Coastguard Worker 	  if (start_of_list)
6346*7304104dSAndroid Build Coastguard Worker 	    {
6347*7304104dSAndroid Build Coastguard Worker 	      base = cu_base;
6348*7304104dSAndroid Build Coastguard Worker 	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
6349*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
6350*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) (readp - offset_array_start - 1));
6351*7304104dSAndroid Build Coastguard Worker 	      start_of_list = false;
6352*7304104dSAndroid Build Coastguard Worker 	    }
6353*7304104dSAndroid Build Coastguard Worker 
6354*7304104dSAndroid Build Coastguard Worker 	  printf ("    %s", dwarf_range_list_encoding_name (kind));
6355*7304104dSAndroid Build Coastguard Worker 	  switch (kind)
6356*7304104dSAndroid Build Coastguard Worker 	    {
6357*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_end_of_list:
6358*7304104dSAndroid Build Coastguard Worker 	      start_of_list = true;
6359*7304104dSAndroid Build Coastguard Worker 	      printf ("\n\n");
6360*7304104dSAndroid Build Coastguard Worker 	      break;
6361*7304104dSAndroid Build Coastguard Worker 
6362*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_base_addressx:
6363*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6364*7304104dSAndroid Build Coastguard Worker 		{
6365*7304104dSAndroid Build Coastguard Worker 		invalid_range:
6366*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("invalid range list data"));
6367*7304104dSAndroid Build Coastguard Worker 		  goto next_table;
6368*7304104dSAndroid Build Coastguard Worker 		}
6369*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
6370*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 "\n", op1);
6371*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
6372*7304104dSAndroid Build Coastguard Worker 		{
6373*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr;
6374*7304104dSAndroid Build Coastguard Worker 		  if (get_indexed_addr (cu, op1, &addr) != 0)
6375*7304104dSAndroid Build Coastguard Worker 		    printf ("      ???\n");
6376*7304104dSAndroid Build Coastguard Worker 		  else
6377*7304104dSAndroid Build Coastguard Worker 		    {
6378*7304104dSAndroid Build Coastguard Worker 		      printf ("      ");
6379*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size, addr, addr);
6380*7304104dSAndroid Build Coastguard Worker 		      printf ("\n");
6381*7304104dSAndroid Build Coastguard Worker 		    }
6382*7304104dSAndroid Build Coastguard Worker 		}
6383*7304104dSAndroid Build Coastguard Worker 	      break;
6384*7304104dSAndroid Build Coastguard Worker 
6385*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_startx_endx:
6386*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6387*7304104dSAndroid Build Coastguard Worker 		goto invalid_range;
6388*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
6389*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6390*7304104dSAndroid Build Coastguard Worker 		goto invalid_range;
6391*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
6392*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
6393*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
6394*7304104dSAndroid Build Coastguard Worker 		{
6395*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr1;
6396*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr2;
6397*7304104dSAndroid Build Coastguard Worker 		  if (get_indexed_addr (cu, op1, &addr1) != 0
6398*7304104dSAndroid Build Coastguard Worker 		      || get_indexed_addr (cu, op2, &addr2) != 0)
6399*7304104dSAndroid Build Coastguard Worker 		    {
6400*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???..\n");
6401*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???\n");
6402*7304104dSAndroid Build Coastguard Worker 		    }
6403*7304104dSAndroid Build Coastguard Worker 		  else
6404*7304104dSAndroid Build Coastguard Worker 		    {
6405*7304104dSAndroid Build Coastguard Worker 		      printf ("      ");
6406*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
6407*7304104dSAndroid Build Coastguard Worker 		      printf ("..\n      ");
6408*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size,
6409*7304104dSAndroid Build Coastguard Worker 					addr2 - 1, addr2);
6410*7304104dSAndroid Build Coastguard Worker 		      printf ("\n");
6411*7304104dSAndroid Build Coastguard Worker 		    }
6412*7304104dSAndroid Build Coastguard Worker 		}
6413*7304104dSAndroid Build Coastguard Worker 	      break;
6414*7304104dSAndroid Build Coastguard Worker 
6415*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_startx_length:
6416*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6417*7304104dSAndroid Build Coastguard Worker 		goto invalid_range;
6418*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
6419*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6420*7304104dSAndroid Build Coastguard Worker 		goto invalid_range;
6421*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
6422*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
6423*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
6424*7304104dSAndroid Build Coastguard Worker 		{
6425*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr1;
6426*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr2;
6427*7304104dSAndroid Build Coastguard Worker 		  if (get_indexed_addr (cu, op1, &addr1) != 0)
6428*7304104dSAndroid Build Coastguard Worker 		    {
6429*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???..\n");
6430*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???\n");
6431*7304104dSAndroid Build Coastguard Worker 		    }
6432*7304104dSAndroid Build Coastguard Worker 		  else
6433*7304104dSAndroid Build Coastguard Worker 		    {
6434*7304104dSAndroid Build Coastguard Worker 		      addr2 = addr1 + op2;
6435*7304104dSAndroid Build Coastguard Worker 		      printf ("      ");
6436*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
6437*7304104dSAndroid Build Coastguard Worker 		      printf ("..\n      ");
6438*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size,
6439*7304104dSAndroid Build Coastguard Worker 					addr2 - 1, addr2);
6440*7304104dSAndroid Build Coastguard Worker 		      printf ("\n");
6441*7304104dSAndroid Build Coastguard Worker 		    }
6442*7304104dSAndroid Build Coastguard Worker 		}
6443*7304104dSAndroid Build Coastguard Worker 	      break;
6444*7304104dSAndroid Build Coastguard Worker 
6445*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_offset_pair:
6446*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6447*7304104dSAndroid Build Coastguard Worker 		goto invalid_range;
6448*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
6449*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6450*7304104dSAndroid Build Coastguard Worker 		goto invalid_range;
6451*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
6452*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
6453*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
6454*7304104dSAndroid Build Coastguard Worker 		{
6455*7304104dSAndroid Build Coastguard Worker 		  op1 += base;
6456*7304104dSAndroid Build Coastguard Worker 		  op2 += base;
6457*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
6458*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op1, op1);
6459*7304104dSAndroid Build Coastguard Worker 		  printf ("..\n      ");
6460*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
6461*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
6462*7304104dSAndroid Build Coastguard Worker 		}
6463*7304104dSAndroid Build Coastguard Worker 	      break;
6464*7304104dSAndroid Build Coastguard Worker 
6465*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_base_address:
6466*7304104dSAndroid Build Coastguard Worker 	      if (address_size == 4)
6467*7304104dSAndroid Build Coastguard Worker 		{
6468*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 4)
6469*7304104dSAndroid Build Coastguard Worker 		    goto invalid_range;
6470*7304104dSAndroid Build Coastguard Worker 		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
6471*7304104dSAndroid Build Coastguard Worker 		}
6472*7304104dSAndroid Build Coastguard Worker 	      else
6473*7304104dSAndroid Build Coastguard Worker 		{
6474*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 8)
6475*7304104dSAndroid Build Coastguard Worker 		    goto invalid_range;
6476*7304104dSAndroid Build Coastguard Worker 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
6477*7304104dSAndroid Build Coastguard Worker 		}
6478*7304104dSAndroid Build Coastguard Worker 	      base = op1;
6479*7304104dSAndroid Build Coastguard Worker 	      printf (" 0x%" PRIx64 "\n", base);
6480*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
6481*7304104dSAndroid Build Coastguard Worker 		{
6482*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
6483*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, base, base);
6484*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
6485*7304104dSAndroid Build Coastguard Worker 		}
6486*7304104dSAndroid Build Coastguard Worker 	      break;
6487*7304104dSAndroid Build Coastguard Worker 
6488*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_start_end:
6489*7304104dSAndroid Build Coastguard Worker 	      if (address_size == 4)
6490*7304104dSAndroid Build Coastguard Worker 		{
6491*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 8)
6492*7304104dSAndroid Build Coastguard Worker 		    goto invalid_range;
6493*7304104dSAndroid Build Coastguard Worker 		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
6494*7304104dSAndroid Build Coastguard Worker 		  op2 = read_4ubyte_unaligned_inc (dbg, readp);
6495*7304104dSAndroid Build Coastguard Worker 		}
6496*7304104dSAndroid Build Coastguard Worker 	      else
6497*7304104dSAndroid Build Coastguard Worker 		{
6498*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 16)
6499*7304104dSAndroid Build Coastguard Worker 		    goto invalid_range;
6500*7304104dSAndroid Build Coastguard Worker 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
6501*7304104dSAndroid Build Coastguard Worker 		  op2 = read_8ubyte_unaligned_inc (dbg, readp);
6502*7304104dSAndroid Build Coastguard Worker 		}
6503*7304104dSAndroid Build Coastguard Worker 	      printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
6504*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
6505*7304104dSAndroid Build Coastguard Worker 		{
6506*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
6507*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op1, op1);
6508*7304104dSAndroid Build Coastguard Worker 		  printf ("..\n      ");
6509*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
6510*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
6511*7304104dSAndroid Build Coastguard Worker 		}
6512*7304104dSAndroid Build Coastguard Worker 	      break;
6513*7304104dSAndroid Build Coastguard Worker 
6514*7304104dSAndroid Build Coastguard Worker 	    case DW_RLE_start_length:
6515*7304104dSAndroid Build Coastguard Worker 	      if (address_size == 4)
6516*7304104dSAndroid Build Coastguard Worker 		{
6517*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 4)
6518*7304104dSAndroid Build Coastguard Worker 		    goto invalid_range;
6519*7304104dSAndroid Build Coastguard Worker 		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
6520*7304104dSAndroid Build Coastguard Worker 		}
6521*7304104dSAndroid Build Coastguard Worker 	      else
6522*7304104dSAndroid Build Coastguard Worker 		{
6523*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 8)
6524*7304104dSAndroid Build Coastguard Worker 		    goto invalid_range;
6525*7304104dSAndroid Build Coastguard Worker 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
6526*7304104dSAndroid Build Coastguard Worker 		}
6527*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
6528*7304104dSAndroid Build Coastguard Worker 		goto invalid_range;
6529*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
6530*7304104dSAndroid Build Coastguard Worker 	      printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
6531*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
6532*7304104dSAndroid Build Coastguard Worker 		{
6533*7304104dSAndroid Build Coastguard Worker 		  op2 = op1 + op2;
6534*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
6535*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op1, op1);
6536*7304104dSAndroid Build Coastguard Worker 		  printf ("..\n      ");
6537*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
6538*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
6539*7304104dSAndroid Build Coastguard Worker 		}
6540*7304104dSAndroid Build Coastguard Worker 	      break;
6541*7304104dSAndroid Build Coastguard Worker 
6542*7304104dSAndroid Build Coastguard Worker 	    default:
6543*7304104dSAndroid Build Coastguard Worker 	      goto invalid_range;
6544*7304104dSAndroid Build Coastguard Worker 	    }
6545*7304104dSAndroid Build Coastguard Worker 	}
6546*7304104dSAndroid Build Coastguard Worker 
6547*7304104dSAndroid Build Coastguard Worker     next_table:
6548*7304104dSAndroid Build Coastguard Worker       if (readp != nexthdr)
6549*7304104dSAndroid Build Coastguard Worker 	{
6550*7304104dSAndroid Build Coastguard Worker           size_t padding = nexthdr - readp;
6551*7304104dSAndroid Build Coastguard Worker           printf (_("   %zu padding bytes\n\n"), padding);
6552*7304104dSAndroid Build Coastguard Worker 	  readp = nexthdr;
6553*7304104dSAndroid Build Coastguard Worker 	}
6554*7304104dSAndroid Build Coastguard Worker     }
6555*7304104dSAndroid Build Coastguard Worker }
6556*7304104dSAndroid Build Coastguard Worker 
6557*7304104dSAndroid Build Coastguard Worker /* Print content of DWARF .debug_ranges section.  */
6558*7304104dSAndroid Build Coastguard Worker static void
print_debug_ranges_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)6559*7304104dSAndroid Build Coastguard Worker print_debug_ranges_section (Dwfl_Module *dwflmod,
6560*7304104dSAndroid Build Coastguard Worker 			    Ebl *ebl, GElf_Ehdr *ehdr,
6561*7304104dSAndroid Build Coastguard Worker 			    Elf_Scn *scn, GElf_Shdr *shdr,
6562*7304104dSAndroid Build Coastguard Worker 			    Dwarf *dbg)
6563*7304104dSAndroid Build Coastguard Worker {
6564*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_ranges, scn);
6565*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
6566*7304104dSAndroid Build Coastguard Worker     return;
6567*7304104dSAndroid Build Coastguard Worker 
6568*7304104dSAndroid Build Coastguard Worker   printf (_("\
6569*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
6570*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
6571*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
6572*7304104dSAndroid Build Coastguard Worker 
6573*7304104dSAndroid Build Coastguard Worker   sort_listptr (&known_rangelistptr, "rangelistptr");
6574*7304104dSAndroid Build Coastguard Worker   size_t listptr_idx = 0;
6575*7304104dSAndroid Build Coastguard Worker 
6576*7304104dSAndroid Build Coastguard Worker   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
6577*7304104dSAndroid Build Coastguard Worker 
6578*7304104dSAndroid Build Coastguard Worker   bool first = true;
6579*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr base = 0;
6580*7304104dSAndroid Build Coastguard Worker   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
6581*7304104dSAndroid Build Coastguard Worker   unsigned char *readp = data->d_buf;
6582*7304104dSAndroid Build Coastguard Worker   Dwarf_CU *last_cu = NULL;
6583*7304104dSAndroid Build Coastguard Worker   while (readp < endp)
6584*7304104dSAndroid Build Coastguard Worker     {
6585*7304104dSAndroid Build Coastguard Worker       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
6586*7304104dSAndroid Build Coastguard Worker       Dwarf_CU *cu = last_cu;
6587*7304104dSAndroid Build Coastguard Worker 
6588*7304104dSAndroid Build Coastguard Worker       if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
6589*7304104dSAndroid Build Coastguard Worker 				      &address_size, NULL, &base, &cu,
6590*7304104dSAndroid Build Coastguard Worker 				      offset, &readp, endp, NULL))
6591*7304104dSAndroid Build Coastguard Worker 	continue;
6592*7304104dSAndroid Build Coastguard Worker 
6593*7304104dSAndroid Build Coastguard Worker       if (last_cu != cu)
6594*7304104dSAndroid Build Coastguard Worker 	{
6595*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Die cudie;
6596*7304104dSAndroid Build Coastguard Worker 	  if (dwarf_cu_die (cu, &cudie,
6597*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL, NULL, NULL,
6598*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL) == NULL)
6599*7304104dSAndroid Build Coastguard Worker 	    printf (_("\n Unknown CU base: "));
6600*7304104dSAndroid Build Coastguard Worker 	  else
6601*7304104dSAndroid Build Coastguard Worker 	    printf (_("\n CU [%6" PRIx64 "] base: "),
6602*7304104dSAndroid Build Coastguard Worker 		    dwarf_dieoffset (&cudie));
6603*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size, base, base);
6604*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
6605*7304104dSAndroid Build Coastguard Worker 	}
6606*7304104dSAndroid Build Coastguard Worker       last_cu = cu;
6607*7304104dSAndroid Build Coastguard Worker 
6608*7304104dSAndroid Build Coastguard Worker       if (unlikely (data->d_size - offset < (size_t) address_size * 2))
6609*7304104dSAndroid Build Coastguard Worker 	{
6610*7304104dSAndroid Build Coastguard Worker 	  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
6611*7304104dSAndroid Build Coastguard Worker 	  break;
6612*7304104dSAndroid Build Coastguard Worker 	}
6613*7304104dSAndroid Build Coastguard Worker 
6614*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr begin;
6615*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr end;
6616*7304104dSAndroid Build Coastguard Worker       if (address_size == 8)
6617*7304104dSAndroid Build Coastguard Worker 	{
6618*7304104dSAndroid Build Coastguard Worker 	  begin = read_8ubyte_unaligned_inc (dbg, readp);
6619*7304104dSAndroid Build Coastguard Worker 	  end = read_8ubyte_unaligned_inc (dbg, readp);
6620*7304104dSAndroid Build Coastguard Worker 	}
6621*7304104dSAndroid Build Coastguard Worker       else
6622*7304104dSAndroid Build Coastguard Worker 	{
6623*7304104dSAndroid Build Coastguard Worker 	  begin = read_4ubyte_unaligned_inc (dbg, readp);
6624*7304104dSAndroid Build Coastguard Worker 	  end = read_4ubyte_unaligned_inc (dbg, readp);
6625*7304104dSAndroid Build Coastguard Worker 	  if (begin == (Dwarf_Addr) (uint32_t) -1)
6626*7304104dSAndroid Build Coastguard Worker 	    begin = (Dwarf_Addr) -1l;
6627*7304104dSAndroid Build Coastguard Worker 	}
6628*7304104dSAndroid Build Coastguard Worker 
6629*7304104dSAndroid Build Coastguard Worker       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
6630*7304104dSAndroid Build Coastguard Worker 	{
6631*7304104dSAndroid Build Coastguard Worker 	  if (first)
6632*7304104dSAndroid Build Coastguard Worker 	    printf (" [%6tx] ", offset);
6633*7304104dSAndroid Build Coastguard Worker 	  else
6634*7304104dSAndroid Build Coastguard Worker 	    printf ("          ");
6635*7304104dSAndroid Build Coastguard Worker 	  puts (_("base address"));
6636*7304104dSAndroid Build Coastguard Worker 	  printf ("          ");
6637*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size, end, end);
6638*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
6639*7304104dSAndroid Build Coastguard Worker 	  base = end;
6640*7304104dSAndroid Build Coastguard Worker 	  first = false;
6641*7304104dSAndroid Build Coastguard Worker 	}
6642*7304104dSAndroid Build Coastguard Worker       else if (begin == 0 && end == 0) /* End of list entry.  */
6643*7304104dSAndroid Build Coastguard Worker 	{
6644*7304104dSAndroid Build Coastguard Worker 	  if (first)
6645*7304104dSAndroid Build Coastguard Worker 	    printf (_(" [%6tx] empty list\n"), offset);
6646*7304104dSAndroid Build Coastguard Worker 	  first = true;
6647*7304104dSAndroid Build Coastguard Worker 	}
6648*7304104dSAndroid Build Coastguard Worker       else
6649*7304104dSAndroid Build Coastguard Worker 	{
6650*7304104dSAndroid Build Coastguard Worker 	  /* We have an address range entry.  */
6651*7304104dSAndroid Build Coastguard Worker 	  if (first)		/* First address range entry in a list.  */
6652*7304104dSAndroid Build Coastguard Worker 	    printf (" [%6tx] ", offset);
6653*7304104dSAndroid Build Coastguard Worker 	  else
6654*7304104dSAndroid Build Coastguard Worker 	    printf ("          ");
6655*7304104dSAndroid Build Coastguard Worker 
6656*7304104dSAndroid Build Coastguard Worker 	  printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
6657*7304104dSAndroid Build Coastguard Worker 	  if (! print_unresolved_addresses)
6658*7304104dSAndroid Build Coastguard Worker 	    {
6659*7304104dSAndroid Build Coastguard Worker 	      printf ("          ");
6660*7304104dSAndroid Build Coastguard Worker 	      print_dwarf_addr (dwflmod, address_size, base + begin,
6661*7304104dSAndroid Build Coastguard Worker 			        base + begin);
6662*7304104dSAndroid Build Coastguard Worker 	      printf ("..\n          ");
6663*7304104dSAndroid Build Coastguard Worker 	      print_dwarf_addr (dwflmod, address_size,
6664*7304104dSAndroid Build Coastguard Worker 				base + end - 1, base + end);
6665*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
6666*7304104dSAndroid Build Coastguard Worker 	    }
6667*7304104dSAndroid Build Coastguard Worker 
6668*7304104dSAndroid Build Coastguard Worker 	  first = false;
6669*7304104dSAndroid Build Coastguard Worker 	}
6670*7304104dSAndroid Build Coastguard Worker     }
6671*7304104dSAndroid Build Coastguard Worker }
6672*7304104dSAndroid Build Coastguard Worker 
6673*7304104dSAndroid Build Coastguard Worker #define REGNAMESZ 16
6674*7304104dSAndroid Build Coastguard Worker static const char *
register_info(Ebl * ebl,unsigned int regno,const Ebl_Register_Location * loc,char name[REGNAMESZ],int * bits,int * type)6675*7304104dSAndroid Build Coastguard Worker register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
6676*7304104dSAndroid Build Coastguard Worker 	       char name[REGNAMESZ], int *bits, int *type)
6677*7304104dSAndroid Build Coastguard Worker {
6678*7304104dSAndroid Build Coastguard Worker   const char *set;
6679*7304104dSAndroid Build Coastguard Worker   const char *pfx;
6680*7304104dSAndroid Build Coastguard Worker   int ignore;
6681*7304104dSAndroid Build Coastguard Worker   ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
6682*7304104dSAndroid Build Coastguard Worker 				 bits ?: &ignore, type ?: &ignore);
6683*7304104dSAndroid Build Coastguard Worker   if (n <= 0)
6684*7304104dSAndroid Build Coastguard Worker     {
6685*7304104dSAndroid Build Coastguard Worker       if (loc != NULL)
6686*7304104dSAndroid Build Coastguard Worker 	snprintf (name, REGNAMESZ, "reg%u", loc->regno);
6687*7304104dSAndroid Build Coastguard Worker       else
6688*7304104dSAndroid Build Coastguard Worker 	snprintf (name, REGNAMESZ, "??? 0x%x", regno);
6689*7304104dSAndroid Build Coastguard Worker       if (bits != NULL)
6690*7304104dSAndroid Build Coastguard Worker 	*bits = loc != NULL ? loc->bits : 0;
6691*7304104dSAndroid Build Coastguard Worker       if (type != NULL)
6692*7304104dSAndroid Build Coastguard Worker 	*type = DW_ATE_unsigned;
6693*7304104dSAndroid Build Coastguard Worker       set = "??? unrecognized";
6694*7304104dSAndroid Build Coastguard Worker     }
6695*7304104dSAndroid Build Coastguard Worker   else
6696*7304104dSAndroid Build Coastguard Worker     {
6697*7304104dSAndroid Build Coastguard Worker       if (bits != NULL && *bits <= 0)
6698*7304104dSAndroid Build Coastguard Worker 	*bits = loc != NULL ? loc->bits : 0;
6699*7304104dSAndroid Build Coastguard Worker       if (type != NULL && *type == DW_ATE_void)
6700*7304104dSAndroid Build Coastguard Worker 	*type = DW_ATE_unsigned;
6701*7304104dSAndroid Build Coastguard Worker 
6702*7304104dSAndroid Build Coastguard Worker     }
6703*7304104dSAndroid Build Coastguard Worker   return set;
6704*7304104dSAndroid Build Coastguard Worker }
6705*7304104dSAndroid Build Coastguard Worker 
6706*7304104dSAndroid Build Coastguard Worker static const unsigned char *
read_encoded(unsigned int encoding,const unsigned char * readp,const unsigned char * const endp,uint64_t * res,Dwarf * dbg)6707*7304104dSAndroid Build Coastguard Worker read_encoded (unsigned int encoding, const unsigned char *readp,
6708*7304104dSAndroid Build Coastguard Worker 	      const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
6709*7304104dSAndroid Build Coastguard Worker {
6710*7304104dSAndroid Build Coastguard Worker   if ((encoding & 0xf) == DW_EH_PE_absptr)
6711*7304104dSAndroid Build Coastguard Worker     encoding = gelf_getclass (dbg->elf) == ELFCLASS32
6712*7304104dSAndroid Build Coastguard Worker       ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
6713*7304104dSAndroid Build Coastguard Worker 
6714*7304104dSAndroid Build Coastguard Worker   switch (encoding & 0xf)
6715*7304104dSAndroid Build Coastguard Worker     {
6716*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_uleb128:
6717*7304104dSAndroid Build Coastguard Worker       if (readp >= endp)
6718*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6719*7304104dSAndroid Build Coastguard Worker       get_uleb128 (*res, readp, endp);
6720*7304104dSAndroid Build Coastguard Worker       break;
6721*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sleb128:
6722*7304104dSAndroid Build Coastguard Worker       if (readp >= endp)
6723*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6724*7304104dSAndroid Build Coastguard Worker       get_sleb128 (*res, readp, endp);
6725*7304104dSAndroid Build Coastguard Worker       break;
6726*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata2:
6727*7304104dSAndroid Build Coastguard Worker       if (readp + 2 > endp)
6728*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6729*7304104dSAndroid Build Coastguard Worker       *res = read_2ubyte_unaligned_inc (dbg, readp);
6730*7304104dSAndroid Build Coastguard Worker       break;
6731*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata4:
6732*7304104dSAndroid Build Coastguard Worker       if (readp + 4 > endp)
6733*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6734*7304104dSAndroid Build Coastguard Worker       *res = read_4ubyte_unaligned_inc (dbg, readp);
6735*7304104dSAndroid Build Coastguard Worker       break;
6736*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata8:
6737*7304104dSAndroid Build Coastguard Worker       if (readp + 8 > endp)
6738*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6739*7304104dSAndroid Build Coastguard Worker       *res = read_8ubyte_unaligned_inc (dbg, readp);
6740*7304104dSAndroid Build Coastguard Worker       break;
6741*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata2:
6742*7304104dSAndroid Build Coastguard Worker       if (readp + 2 > endp)
6743*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6744*7304104dSAndroid Build Coastguard Worker       *res = read_2sbyte_unaligned_inc (dbg, readp);
6745*7304104dSAndroid Build Coastguard Worker       break;
6746*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata4:
6747*7304104dSAndroid Build Coastguard Worker       if (readp + 4 > endp)
6748*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6749*7304104dSAndroid Build Coastguard Worker       *res = read_4sbyte_unaligned_inc (dbg, readp);
6750*7304104dSAndroid Build Coastguard Worker       break;
6751*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata8:
6752*7304104dSAndroid Build Coastguard Worker       if (readp + 8 > endp)
6753*7304104dSAndroid Build Coastguard Worker 	goto invalid;
6754*7304104dSAndroid Build Coastguard Worker       *res = read_8sbyte_unaligned_inc (dbg, readp);
6755*7304104dSAndroid Build Coastguard Worker       break;
6756*7304104dSAndroid Build Coastguard Worker     default:
6757*7304104dSAndroid Build Coastguard Worker     invalid:
6758*7304104dSAndroid Build Coastguard Worker       error (1, 0,
6759*7304104dSAndroid Build Coastguard Worker 	     _("invalid encoding"));
6760*7304104dSAndroid Build Coastguard Worker     }
6761*7304104dSAndroid Build Coastguard Worker 
6762*7304104dSAndroid Build Coastguard Worker   return readp;
6763*7304104dSAndroid Build Coastguard Worker }
6764*7304104dSAndroid Build Coastguard Worker 
6765*7304104dSAndroid Build Coastguard Worker static const char *
regname(Ebl * ebl,unsigned int regno,char * regnamebuf)6766*7304104dSAndroid Build Coastguard Worker regname (Ebl *ebl, unsigned int regno, char *regnamebuf)
6767*7304104dSAndroid Build Coastguard Worker {
6768*7304104dSAndroid Build Coastguard Worker   register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
6769*7304104dSAndroid Build Coastguard Worker 
6770*7304104dSAndroid Build Coastguard Worker   return regnamebuf;
6771*7304104dSAndroid Build Coastguard Worker }
6772*7304104dSAndroid Build Coastguard Worker 
6773*7304104dSAndroid Build Coastguard Worker static void
print_cfa_program(const unsigned char * readp,const unsigned char * const endp,Dwarf_Word vma_base,unsigned int code_align,int data_align,unsigned int version,unsigned int ptr_size,unsigned int encoding,Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Dwarf * dbg)6774*7304104dSAndroid Build Coastguard Worker print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
6775*7304104dSAndroid Build Coastguard Worker 		   Dwarf_Word vma_base, unsigned int code_align,
6776*7304104dSAndroid Build Coastguard Worker 		   int data_align,
6777*7304104dSAndroid Build Coastguard Worker 		   unsigned int version, unsigned int ptr_size,
6778*7304104dSAndroid Build Coastguard Worker 		   unsigned int encoding,
6779*7304104dSAndroid Build Coastguard Worker 		   Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Dwarf *dbg)
6780*7304104dSAndroid Build Coastguard Worker {
6781*7304104dSAndroid Build Coastguard Worker   char regnamebuf[REGNAMESZ];
6782*7304104dSAndroid Build Coastguard Worker 
6783*7304104dSAndroid Build Coastguard Worker   puts ("\n   Program:");
6784*7304104dSAndroid Build Coastguard Worker   Dwarf_Word pc = vma_base;
6785*7304104dSAndroid Build Coastguard Worker   while (readp < endp)
6786*7304104dSAndroid Build Coastguard Worker     {
6787*7304104dSAndroid Build Coastguard Worker       unsigned int opcode = *readp++;
6788*7304104dSAndroid Build Coastguard Worker 
6789*7304104dSAndroid Build Coastguard Worker       if (opcode < DW_CFA_advance_loc)
6790*7304104dSAndroid Build Coastguard Worker 	/* Extended opcode.  */
6791*7304104dSAndroid Build Coastguard Worker 	switch (opcode)
6792*7304104dSAndroid Build Coastguard Worker 	  {
6793*7304104dSAndroid Build Coastguard Worker 	    uint64_t op1;
6794*7304104dSAndroid Build Coastguard Worker 	    int64_t sop1;
6795*7304104dSAndroid Build Coastguard Worker 	    uint64_t op2;
6796*7304104dSAndroid Build Coastguard Worker 	    int64_t sop2;
6797*7304104dSAndroid Build Coastguard Worker 
6798*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_nop:
6799*7304104dSAndroid Build Coastguard Worker 	    puts ("     nop");
6800*7304104dSAndroid Build Coastguard Worker 	    break;
6801*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_set_loc:
6802*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6803*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6804*7304104dSAndroid Build Coastguard Worker 	    readp = read_encoded (encoding, readp, endp, &op1, dbg);
6805*7304104dSAndroid Build Coastguard Worker 	    printf ("     set_loc %#" PRIx64 " to %#" PRIx64 "\n",
6806*7304104dSAndroid Build Coastguard Worker 		    op1, pc = vma_base + op1);
6807*7304104dSAndroid Build Coastguard Worker 	    break;
6808*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_advance_loc1:
6809*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6810*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6811*7304104dSAndroid Build Coastguard Worker 	    printf ("     advance_loc1 %u to %#" PRIx64 "\n",
6812*7304104dSAndroid Build Coastguard Worker 		    *readp, pc += *readp * code_align);
6813*7304104dSAndroid Build Coastguard Worker 	    ++readp;
6814*7304104dSAndroid Build Coastguard Worker 	    break;
6815*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_advance_loc2:
6816*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 2)
6817*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6818*7304104dSAndroid Build Coastguard Worker 	    op1 = read_2ubyte_unaligned_inc (dbg, readp);
6819*7304104dSAndroid Build Coastguard Worker 	    printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
6820*7304104dSAndroid Build Coastguard Worker 		    op1, pc += op1 * code_align);
6821*7304104dSAndroid Build Coastguard Worker 	    break;
6822*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_advance_loc4:
6823*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 4)
6824*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6825*7304104dSAndroid Build Coastguard Worker 	    op1 = read_4ubyte_unaligned_inc (dbg, readp);
6826*7304104dSAndroid Build Coastguard Worker 	    printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
6827*7304104dSAndroid Build Coastguard Worker 		    op1, pc += op1 * code_align);
6828*7304104dSAndroid Build Coastguard Worker 	    break;
6829*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_offset_extended:
6830*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6831*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6832*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6833*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6834*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6835*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op2, readp, endp);
6836*7304104dSAndroid Build Coastguard Worker 	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
6837*7304104dSAndroid Build Coastguard Worker 		    "\n",
6838*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf), op2 * data_align);
6839*7304104dSAndroid Build Coastguard Worker 	    break;
6840*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_restore_extended:
6841*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6842*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6843*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6844*7304104dSAndroid Build Coastguard Worker 	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
6845*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf));
6846*7304104dSAndroid Build Coastguard Worker 	    break;
6847*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_undefined:
6848*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6849*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6850*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6851*7304104dSAndroid Build Coastguard Worker 	    printf ("     undefined r%" PRIu64 " (%s)\n", op1,
6852*7304104dSAndroid Build Coastguard Worker 		    regname (ebl, op1, regnamebuf));
6853*7304104dSAndroid Build Coastguard Worker 	    break;
6854*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_same_value:
6855*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6856*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6857*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6858*7304104dSAndroid Build Coastguard Worker 	    printf ("     same_value r%" PRIu64 " (%s)\n", op1,
6859*7304104dSAndroid Build Coastguard Worker 		    regname (ebl, op1, regnamebuf));
6860*7304104dSAndroid Build Coastguard Worker 	    break;
6861*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_register:
6862*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6863*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6864*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6865*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6866*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6867*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op2, readp, endp);
6868*7304104dSAndroid Build Coastguard Worker 	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
6869*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf), op2,
6870*7304104dSAndroid Build Coastguard Worker 		    regname (ebl, op2, regnamebuf));
6871*7304104dSAndroid Build Coastguard Worker 	    break;
6872*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_remember_state:
6873*7304104dSAndroid Build Coastguard Worker 	    puts ("     remember_state");
6874*7304104dSAndroid Build Coastguard Worker 	    break;
6875*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_restore_state:
6876*7304104dSAndroid Build Coastguard Worker 	    puts ("     restore_state");
6877*7304104dSAndroid Build Coastguard Worker 	    break;
6878*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_def_cfa:
6879*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6880*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6881*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6882*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6883*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6884*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op2, readp, endp);
6885*7304104dSAndroid Build Coastguard Worker 	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
6886*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf), op2);
6887*7304104dSAndroid Build Coastguard Worker 	    break;
6888*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_def_cfa_register:
6889*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6890*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6891*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6892*7304104dSAndroid Build Coastguard Worker 	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
6893*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf));
6894*7304104dSAndroid Build Coastguard Worker 	    break;
6895*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_def_cfa_offset:
6896*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6897*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6898*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6899*7304104dSAndroid Build Coastguard Worker 	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
6900*7304104dSAndroid Build Coastguard Worker 	    break;
6901*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_def_cfa_expression:
6902*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6903*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6904*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);	/* Length of DW_FORM_block.  */
6905*7304104dSAndroid Build Coastguard Worker 	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
6906*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < op1)
6907*7304104dSAndroid Build Coastguard Worker 	      {
6908*7304104dSAndroid Build Coastguard Worker 	    invalid:
6909*7304104dSAndroid Build Coastguard Worker 	        fputs (_("         <INVALID DATA>\n"), stdout);
6910*7304104dSAndroid Build Coastguard Worker 		return;
6911*7304104dSAndroid Build Coastguard Worker 	      }
6912*7304104dSAndroid Build Coastguard Worker 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
6913*7304104dSAndroid Build Coastguard Worker 		       op1, readp);
6914*7304104dSAndroid Build Coastguard Worker 	    readp += op1;
6915*7304104dSAndroid Build Coastguard Worker 	    break;
6916*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_expression:
6917*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6918*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6919*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6920*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6921*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6922*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
6923*7304104dSAndroid Build Coastguard Worker 	    printf ("     expression r%" PRIu64 " (%s) \n",
6924*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf));
6925*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < op2)
6926*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6927*7304104dSAndroid Build Coastguard Worker 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
6928*7304104dSAndroid Build Coastguard Worker 		       op2, readp);
6929*7304104dSAndroid Build Coastguard Worker 	    readp += op2;
6930*7304104dSAndroid Build Coastguard Worker 	    break;
6931*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_offset_extended_sf:
6932*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6933*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6934*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6935*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6936*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6937*7304104dSAndroid Build Coastguard Worker 	    get_sleb128 (sop2, readp, endp);
6938*7304104dSAndroid Build Coastguard Worker 	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
6939*7304104dSAndroid Build Coastguard Worker 		    PRId64 "\n",
6940*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
6941*7304104dSAndroid Build Coastguard Worker 	    break;
6942*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_def_cfa_sf:
6943*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6944*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6945*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6946*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6947*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6948*7304104dSAndroid Build Coastguard Worker 	    get_sleb128 (sop2, readp, endp);
6949*7304104dSAndroid Build Coastguard Worker 	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
6950*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
6951*7304104dSAndroid Build Coastguard Worker 	    break;
6952*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_def_cfa_offset_sf:
6953*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6954*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6955*7304104dSAndroid Build Coastguard Worker 	    get_sleb128 (sop1, readp, endp);
6956*7304104dSAndroid Build Coastguard Worker 	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
6957*7304104dSAndroid Build Coastguard Worker 	    break;
6958*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_val_offset:
6959*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6960*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6961*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6962*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6963*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6964*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op2, readp, endp);
6965*7304104dSAndroid Build Coastguard Worker 	    printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
6966*7304104dSAndroid Build Coastguard Worker 		    op1, op2 * data_align);
6967*7304104dSAndroid Build Coastguard Worker 	    break;
6968*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_val_offset_sf:
6969*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6970*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6971*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6972*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6973*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6974*7304104dSAndroid Build Coastguard Worker 	    get_sleb128 (sop2, readp, endp);
6975*7304104dSAndroid Build Coastguard Worker 	    printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
6976*7304104dSAndroid Build Coastguard Worker 		    op1, sop2 * data_align);
6977*7304104dSAndroid Build Coastguard Worker 	    break;
6978*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_val_expression:
6979*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6980*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6981*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
6982*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
6983*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6984*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
6985*7304104dSAndroid Build Coastguard Worker 	    printf ("     val_expression r%" PRIu64 " (%s)\n",
6986*7304104dSAndroid Build Coastguard Worker 		    op1, regname (ebl, op1, regnamebuf));
6987*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < op2)
6988*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6989*7304104dSAndroid Build Coastguard Worker 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
6990*7304104dSAndroid Build Coastguard Worker 		       NULL, op2, readp);
6991*7304104dSAndroid Build Coastguard Worker 	    readp += op2;
6992*7304104dSAndroid Build Coastguard Worker 	    break;
6993*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_MIPS_advance_loc8:
6994*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 8)
6995*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
6996*7304104dSAndroid Build Coastguard Worker 	    op1 = read_8ubyte_unaligned_inc (dbg, readp);
6997*7304104dSAndroid Build Coastguard Worker 	    printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
6998*7304104dSAndroid Build Coastguard Worker 		    op1, pc += op1 * code_align);
6999*7304104dSAndroid Build Coastguard Worker 	    break;
7000*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_GNU_window_save:  /* DW_CFA_AARCH64_negate_ra_state  */
7001*7304104dSAndroid Build Coastguard Worker 	    if (ehdr->e_machine == EM_AARCH64)
7002*7304104dSAndroid Build Coastguard Worker 	      puts ("     AARCH64_negate_ra_state");
7003*7304104dSAndroid Build Coastguard Worker 	    else
7004*7304104dSAndroid Build Coastguard Worker 	      puts ("     GNU_window_save");
7005*7304104dSAndroid Build Coastguard Worker 	    break;
7006*7304104dSAndroid Build Coastguard Worker 	  case DW_CFA_GNU_args_size:
7007*7304104dSAndroid Build Coastguard Worker 	    if ((uint64_t) (endp - readp) < 1)
7008*7304104dSAndroid Build Coastguard Worker 	      goto invalid;
7009*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (op1, readp, endp);
7010*7304104dSAndroid Build Coastguard Worker 	    printf ("     args_size %" PRIu64 "\n", op1);
7011*7304104dSAndroid Build Coastguard Worker 	    break;
7012*7304104dSAndroid Build Coastguard Worker 	  default:
7013*7304104dSAndroid Build Coastguard Worker 	    printf ("     ??? (%u)\n", opcode);
7014*7304104dSAndroid Build Coastguard Worker 	    break;
7015*7304104dSAndroid Build Coastguard Worker 	  }
7016*7304104dSAndroid Build Coastguard Worker       else if (opcode < DW_CFA_offset)
7017*7304104dSAndroid Build Coastguard Worker 	printf ("     advance_loc %u to %#" PRIx64 "\n",
7018*7304104dSAndroid Build Coastguard Worker 		opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
7019*7304104dSAndroid Build Coastguard Worker       else if (opcode < DW_CFA_restore)
7020*7304104dSAndroid Build Coastguard Worker 	{
7021*7304104dSAndroid Build Coastguard Worker 	  uint64_t offset;
7022*7304104dSAndroid Build Coastguard Worker 	  if ((uint64_t) (endp - readp) < 1)
7023*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
7024*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (offset, readp, endp);
7025*7304104dSAndroid Build Coastguard Worker 	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
7026*7304104dSAndroid Build Coastguard Worker 		  opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf),
7027*7304104dSAndroid Build Coastguard Worker 		  offset * data_align);
7028*7304104dSAndroid Build Coastguard Worker 	}
7029*7304104dSAndroid Build Coastguard Worker       else
7030*7304104dSAndroid Build Coastguard Worker 	printf ("     restore r%u (%s)\n",
7031*7304104dSAndroid Build Coastguard Worker 		opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf));
7032*7304104dSAndroid Build Coastguard Worker     }
7033*7304104dSAndroid Build Coastguard Worker }
7034*7304104dSAndroid Build Coastguard Worker 
7035*7304104dSAndroid Build Coastguard Worker 
7036*7304104dSAndroid Build Coastguard Worker static unsigned int
encoded_ptr_size(int encoding,unsigned int ptr_size)7037*7304104dSAndroid Build Coastguard Worker encoded_ptr_size (int encoding, unsigned int ptr_size)
7038*7304104dSAndroid Build Coastguard Worker {
7039*7304104dSAndroid Build Coastguard Worker   switch (encoding & 7)
7040*7304104dSAndroid Build Coastguard Worker     {
7041*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata4:
7042*7304104dSAndroid Build Coastguard Worker       return 4;
7043*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata8:
7044*7304104dSAndroid Build Coastguard Worker       return 8;
7045*7304104dSAndroid Build Coastguard Worker     case 0:
7046*7304104dSAndroid Build Coastguard Worker       return ptr_size;
7047*7304104dSAndroid Build Coastguard Worker     }
7048*7304104dSAndroid Build Coastguard Worker 
7049*7304104dSAndroid Build Coastguard Worker   fprintf (stderr, "Unsupported pointer encoding: %#x, "
7050*7304104dSAndroid Build Coastguard Worker 	   "assuming pointer size of %d.\n", encoding, ptr_size);
7051*7304104dSAndroid Build Coastguard Worker   return ptr_size;
7052*7304104dSAndroid Build Coastguard Worker }
7053*7304104dSAndroid Build Coastguard Worker 
7054*7304104dSAndroid Build Coastguard Worker 
7055*7304104dSAndroid Build Coastguard Worker static unsigned int
print_encoding(unsigned int val)7056*7304104dSAndroid Build Coastguard Worker print_encoding (unsigned int val)
7057*7304104dSAndroid Build Coastguard Worker {
7058*7304104dSAndroid Build Coastguard Worker   switch (val & 0xf)
7059*7304104dSAndroid Build Coastguard Worker     {
7060*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_absptr:
7061*7304104dSAndroid Build Coastguard Worker       fputs ("absptr", stdout);
7062*7304104dSAndroid Build Coastguard Worker       break;
7063*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_uleb128:
7064*7304104dSAndroid Build Coastguard Worker       fputs ("uleb128", stdout);
7065*7304104dSAndroid Build Coastguard Worker       break;
7066*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata2:
7067*7304104dSAndroid Build Coastguard Worker       fputs ("udata2", stdout);
7068*7304104dSAndroid Build Coastguard Worker       break;
7069*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata4:
7070*7304104dSAndroid Build Coastguard Worker       fputs ("udata4", stdout);
7071*7304104dSAndroid Build Coastguard Worker       break;
7072*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_udata8:
7073*7304104dSAndroid Build Coastguard Worker       fputs ("udata8", stdout);
7074*7304104dSAndroid Build Coastguard Worker       break;
7075*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sleb128:
7076*7304104dSAndroid Build Coastguard Worker       fputs ("sleb128", stdout);
7077*7304104dSAndroid Build Coastguard Worker       break;
7078*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata2:
7079*7304104dSAndroid Build Coastguard Worker       fputs ("sdata2", stdout);
7080*7304104dSAndroid Build Coastguard Worker       break;
7081*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata4:
7082*7304104dSAndroid Build Coastguard Worker       fputs ("sdata4", stdout);
7083*7304104dSAndroid Build Coastguard Worker       break;
7084*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_sdata8:
7085*7304104dSAndroid Build Coastguard Worker       fputs ("sdata8", stdout);
7086*7304104dSAndroid Build Coastguard Worker       break;
7087*7304104dSAndroid Build Coastguard Worker     default:
7088*7304104dSAndroid Build Coastguard Worker       /* We did not use any of the bits after all.  */
7089*7304104dSAndroid Build Coastguard Worker       return val;
7090*7304104dSAndroid Build Coastguard Worker     }
7091*7304104dSAndroid Build Coastguard Worker 
7092*7304104dSAndroid Build Coastguard Worker   return val & ~0xf;
7093*7304104dSAndroid Build Coastguard Worker }
7094*7304104dSAndroid Build Coastguard Worker 
7095*7304104dSAndroid Build Coastguard Worker 
7096*7304104dSAndroid Build Coastguard Worker static unsigned int
print_relinfo(unsigned int val)7097*7304104dSAndroid Build Coastguard Worker print_relinfo (unsigned int val)
7098*7304104dSAndroid Build Coastguard Worker {
7099*7304104dSAndroid Build Coastguard Worker   switch (val & 0x70)
7100*7304104dSAndroid Build Coastguard Worker     {
7101*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_pcrel:
7102*7304104dSAndroid Build Coastguard Worker       fputs ("pcrel", stdout);
7103*7304104dSAndroid Build Coastguard Worker       break;
7104*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_textrel:
7105*7304104dSAndroid Build Coastguard Worker       fputs ("textrel", stdout);
7106*7304104dSAndroid Build Coastguard Worker       break;
7107*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_datarel:
7108*7304104dSAndroid Build Coastguard Worker       fputs ("datarel", stdout);
7109*7304104dSAndroid Build Coastguard Worker       break;
7110*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_funcrel:
7111*7304104dSAndroid Build Coastguard Worker       fputs ("funcrel", stdout);
7112*7304104dSAndroid Build Coastguard Worker       break;
7113*7304104dSAndroid Build Coastguard Worker     case DW_EH_PE_aligned:
7114*7304104dSAndroid Build Coastguard Worker       fputs ("aligned", stdout);
7115*7304104dSAndroid Build Coastguard Worker       break;
7116*7304104dSAndroid Build Coastguard Worker     default:
7117*7304104dSAndroid Build Coastguard Worker       return val;
7118*7304104dSAndroid Build Coastguard Worker     }
7119*7304104dSAndroid Build Coastguard Worker 
7120*7304104dSAndroid Build Coastguard Worker   return val & ~0x70;
7121*7304104dSAndroid Build Coastguard Worker }
7122*7304104dSAndroid Build Coastguard Worker 
7123*7304104dSAndroid Build Coastguard Worker 
7124*7304104dSAndroid Build Coastguard Worker static void
print_encoding_base(const char * pfx,unsigned int fde_encoding)7125*7304104dSAndroid Build Coastguard Worker print_encoding_base (const char *pfx, unsigned int fde_encoding)
7126*7304104dSAndroid Build Coastguard Worker {
7127*7304104dSAndroid Build Coastguard Worker   printf ("(%s", pfx);
7128*7304104dSAndroid Build Coastguard Worker 
7129*7304104dSAndroid Build Coastguard Worker   if (fde_encoding == DW_EH_PE_omit)
7130*7304104dSAndroid Build Coastguard Worker     puts ("omit)");
7131*7304104dSAndroid Build Coastguard Worker   else
7132*7304104dSAndroid Build Coastguard Worker     {
7133*7304104dSAndroid Build Coastguard Worker       unsigned int w = fde_encoding;
7134*7304104dSAndroid Build Coastguard Worker 
7135*7304104dSAndroid Build Coastguard Worker       w = print_encoding (w);
7136*7304104dSAndroid Build Coastguard Worker 
7137*7304104dSAndroid Build Coastguard Worker       if (w & 0x70)
7138*7304104dSAndroid Build Coastguard Worker 	{
7139*7304104dSAndroid Build Coastguard Worker 	  if (w != fde_encoding)
7140*7304104dSAndroid Build Coastguard Worker 	    fputc_unlocked (' ', stdout);
7141*7304104dSAndroid Build Coastguard Worker 
7142*7304104dSAndroid Build Coastguard Worker 	  w = print_relinfo (w);
7143*7304104dSAndroid Build Coastguard Worker 	}
7144*7304104dSAndroid Build Coastguard Worker 
7145*7304104dSAndroid Build Coastguard Worker       if (w != 0)
7146*7304104dSAndroid Build Coastguard Worker 	printf ("%s%x", w != fde_encoding ? " " : "", w);
7147*7304104dSAndroid Build Coastguard Worker 
7148*7304104dSAndroid Build Coastguard Worker       puts (")");
7149*7304104dSAndroid Build Coastguard Worker     }
7150*7304104dSAndroid Build Coastguard Worker }
7151*7304104dSAndroid Build Coastguard Worker 
7152*7304104dSAndroid Build Coastguard Worker 
7153*7304104dSAndroid Build Coastguard Worker static void
print_debug_frame_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)7154*7304104dSAndroid Build Coastguard Worker print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
7155*7304104dSAndroid Build Coastguard Worker 			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
7156*7304104dSAndroid Build Coastguard Worker {
7157*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
7158*7304104dSAndroid Build Coastguard Worker   /* We know this call will succeed since it did in the caller.  */
7159*7304104dSAndroid Build Coastguard Worker   (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
7160*7304104dSAndroid Build Coastguard Worker   const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
7161*7304104dSAndroid Build Coastguard Worker 
7162*7304104dSAndroid Build Coastguard Worker   /* Needed if we find PC-relative addresses.  */
7163*7304104dSAndroid Build Coastguard Worker   GElf_Addr bias;
7164*7304104dSAndroid Build Coastguard Worker   if (dwfl_module_getelf (dwflmod, &bias) == NULL)
7165*7304104dSAndroid Build Coastguard Worker     {
7166*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get ELF: %s"), dwfl_errmsg (-1));
7167*7304104dSAndroid Build Coastguard Worker       return;
7168*7304104dSAndroid Build Coastguard Worker     }
7169*7304104dSAndroid Build Coastguard Worker 
7170*7304104dSAndroid Build Coastguard Worker   bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
7171*7304104dSAndroid Build Coastguard Worker   Elf_Data *data;
7172*7304104dSAndroid Build Coastguard Worker   if (is_eh_frame)
7173*7304104dSAndroid Build Coastguard Worker     {
7174*7304104dSAndroid Build Coastguard Worker       data = elf_rawdata (scn, NULL);
7175*7304104dSAndroid Build Coastguard Worker       if (data == NULL)
7176*7304104dSAndroid Build Coastguard Worker 	{
7177*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot get %s content: %s"),
7178*7304104dSAndroid Build Coastguard Worker 		 scnname, elf_errmsg (-1));
7179*7304104dSAndroid Build Coastguard Worker 	  return;
7180*7304104dSAndroid Build Coastguard Worker 	}
7181*7304104dSAndroid Build Coastguard Worker     }
7182*7304104dSAndroid Build Coastguard Worker   else
7183*7304104dSAndroid Build Coastguard Worker     {
7184*7304104dSAndroid Build Coastguard Worker       data = get_debug_elf_data (dbg, ebl, IDX_debug_frame, scn);
7185*7304104dSAndroid Build Coastguard Worker       if (data == NULL)
7186*7304104dSAndroid Build Coastguard Worker 	return;
7187*7304104dSAndroid Build Coastguard Worker     }
7188*7304104dSAndroid Build Coastguard Worker 
7189*7304104dSAndroid Build Coastguard Worker   if (is_eh_frame)
7190*7304104dSAndroid Build Coastguard Worker     printf (_("\
7191*7304104dSAndroid Build Coastguard Worker \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7192*7304104dSAndroid Build Coastguard Worker 	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
7193*7304104dSAndroid Build Coastguard Worker   else
7194*7304104dSAndroid Build Coastguard Worker     printf (_("\
7195*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
7196*7304104dSAndroid Build Coastguard Worker 	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
7197*7304104dSAndroid Build Coastguard Worker 
7198*7304104dSAndroid Build Coastguard Worker   struct cieinfo
7199*7304104dSAndroid Build Coastguard Worker   {
7200*7304104dSAndroid Build Coastguard Worker     ptrdiff_t cie_offset;
7201*7304104dSAndroid Build Coastguard Worker     const char *augmentation;
7202*7304104dSAndroid Build Coastguard Worker     unsigned int code_alignment_factor;
7203*7304104dSAndroid Build Coastguard Worker     unsigned int data_alignment_factor;
7204*7304104dSAndroid Build Coastguard Worker     uint8_t address_size;
7205*7304104dSAndroid Build Coastguard Worker     uint8_t fde_encoding;
7206*7304104dSAndroid Build Coastguard Worker     uint8_t lsda_encoding;
7207*7304104dSAndroid Build Coastguard Worker     struct cieinfo *next;
7208*7304104dSAndroid Build Coastguard Worker   } *cies = NULL;
7209*7304104dSAndroid Build Coastguard Worker 
7210*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = data->d_buf;
7211*7304104dSAndroid Build Coastguard Worker   const unsigned char *const dataend = ((unsigned char *) data->d_buf
7212*7304104dSAndroid Build Coastguard Worker 					+ data->d_size);
7213*7304104dSAndroid Build Coastguard Worker   while (readp < dataend)
7214*7304104dSAndroid Build Coastguard Worker     {
7215*7304104dSAndroid Build Coastguard Worker       if (unlikely (readp + 4 > dataend))
7216*7304104dSAndroid Build Coastguard Worker 	{
7217*7304104dSAndroid Build Coastguard Worker 	invalid_data:
7218*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("invalid data in section [%zu] '%s'"),
7219*7304104dSAndroid Build Coastguard Worker 		     elf_ndxscn (scn), scnname);
7220*7304104dSAndroid Build Coastguard Worker 	      return;
7221*7304104dSAndroid Build Coastguard Worker 	}
7222*7304104dSAndroid Build Coastguard Worker 
7223*7304104dSAndroid Build Coastguard Worker       /* At the beginning there must be a CIE.  There can be multiple,
7224*7304104dSAndroid Build Coastguard Worker 	 hence we test tis in a loop.  */
7225*7304104dSAndroid Build Coastguard Worker       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
7226*7304104dSAndroid Build Coastguard Worker 
7227*7304104dSAndroid Build Coastguard Worker       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
7228*7304104dSAndroid Build Coastguard Worker       unsigned int length = 4;
7229*7304104dSAndroid Build Coastguard Worker       if (unlikely (unit_length == 0xffffffff))
7230*7304104dSAndroid Build Coastguard Worker 	{
7231*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (readp + 8 > dataend))
7232*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7233*7304104dSAndroid Build Coastguard Worker 
7234*7304104dSAndroid Build Coastguard Worker 	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
7235*7304104dSAndroid Build Coastguard Worker 	  length = 8;
7236*7304104dSAndroid Build Coastguard Worker 	}
7237*7304104dSAndroid Build Coastguard Worker 
7238*7304104dSAndroid Build Coastguard Worker       if (unlikely (unit_length == 0))
7239*7304104dSAndroid Build Coastguard Worker 	{
7240*7304104dSAndroid Build Coastguard Worker 	  printf (_("\n [%6tx] Zero terminator\n"), offset);
7241*7304104dSAndroid Build Coastguard Worker 	  continue;
7242*7304104dSAndroid Build Coastguard Worker 	}
7243*7304104dSAndroid Build Coastguard Worker 
7244*7304104dSAndroid Build Coastguard Worker       Dwarf_Word maxsize = dataend - readp;
7245*7304104dSAndroid Build Coastguard Worker       if (unlikely (unit_length > maxsize))
7246*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
7247*7304104dSAndroid Build Coastguard Worker 
7248*7304104dSAndroid Build Coastguard Worker       unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
7249*7304104dSAndroid Build Coastguard Worker 
7250*7304104dSAndroid Build Coastguard Worker       ptrdiff_t start = readp - (unsigned char *) data->d_buf;
7251*7304104dSAndroid Build Coastguard Worker       const unsigned char *const cieend = readp + unit_length;
7252*7304104dSAndroid Build Coastguard Worker       if (unlikely (cieend > dataend))
7253*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
7254*7304104dSAndroid Build Coastguard Worker 
7255*7304104dSAndroid Build Coastguard Worker       Dwarf_Off cie_id;
7256*7304104dSAndroid Build Coastguard Worker       if (length == 4)
7257*7304104dSAndroid Build Coastguard Worker 	{
7258*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (cieend - readp < 4))
7259*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7260*7304104dSAndroid Build Coastguard Worker 	  cie_id = read_4ubyte_unaligned_inc (dbg, readp);
7261*7304104dSAndroid Build Coastguard Worker 	  if (!is_eh_frame && cie_id == DW_CIE_ID_32)
7262*7304104dSAndroid Build Coastguard Worker 	    cie_id = DW_CIE_ID_64;
7263*7304104dSAndroid Build Coastguard Worker 	}
7264*7304104dSAndroid Build Coastguard Worker       else
7265*7304104dSAndroid Build Coastguard Worker 	{
7266*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (cieend - readp < 8))
7267*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7268*7304104dSAndroid Build Coastguard Worker 	  cie_id = read_8ubyte_unaligned_inc (dbg, readp);
7269*7304104dSAndroid Build Coastguard Worker 	}
7270*7304104dSAndroid Build Coastguard Worker 
7271*7304104dSAndroid Build Coastguard Worker       uint_fast8_t version = 2;
7272*7304104dSAndroid Build Coastguard Worker       unsigned int code_alignment_factor;
7273*7304104dSAndroid Build Coastguard Worker       int data_alignment_factor;
7274*7304104dSAndroid Build Coastguard Worker       unsigned int fde_encoding = 0;
7275*7304104dSAndroid Build Coastguard Worker       unsigned int lsda_encoding = 0;
7276*7304104dSAndroid Build Coastguard Worker       Dwarf_Word initial_location = 0;
7277*7304104dSAndroid Build Coastguard Worker       Dwarf_Word vma_base = 0;
7278*7304104dSAndroid Build Coastguard Worker 
7279*7304104dSAndroid Build Coastguard Worker       if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
7280*7304104dSAndroid Build Coastguard Worker 	{
7281*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (cieend - readp < 2))
7282*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7283*7304104dSAndroid Build Coastguard Worker 	  version = *readp++;
7284*7304104dSAndroid Build Coastguard Worker 	  const char *const augmentation = (const char *) readp;
7285*7304104dSAndroid Build Coastguard Worker 	  readp = memchr (readp, '\0', cieend - readp);
7286*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (readp == NULL))
7287*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7288*7304104dSAndroid Build Coastguard Worker 	  ++readp;
7289*7304104dSAndroid Build Coastguard Worker 
7290*7304104dSAndroid Build Coastguard Worker 	  uint_fast8_t segment_size = 0;
7291*7304104dSAndroid Build Coastguard Worker 	  if (version >= 4)
7292*7304104dSAndroid Build Coastguard Worker 	    {
7293*7304104dSAndroid Build Coastguard Worker 	      if (cieend - readp < 5)
7294*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
7295*7304104dSAndroid Build Coastguard Worker 	      ptr_size = *readp++;
7296*7304104dSAndroid Build Coastguard Worker 	      segment_size = *readp++;
7297*7304104dSAndroid Build Coastguard Worker 	    }
7298*7304104dSAndroid Build Coastguard Worker 
7299*7304104dSAndroid Build Coastguard Worker 	  if (cieend - readp < 1)
7300*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7301*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (code_alignment_factor, readp, cieend);
7302*7304104dSAndroid Build Coastguard Worker 	  if (cieend - readp < 1)
7303*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7304*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (data_alignment_factor, readp, cieend);
7305*7304104dSAndroid Build Coastguard Worker 
7306*7304104dSAndroid Build Coastguard Worker 	  /* In some variant for unwind data there is another field.  */
7307*7304104dSAndroid Build Coastguard Worker 	  if (strcmp (augmentation, "eh") == 0)
7308*7304104dSAndroid Build Coastguard Worker 	    readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
7309*7304104dSAndroid Build Coastguard Worker 
7310*7304104dSAndroid Build Coastguard Worker 	  unsigned int return_address_register;
7311*7304104dSAndroid Build Coastguard Worker 	  if (cieend - readp < 1)
7312*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
7313*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (version == 1))
7314*7304104dSAndroid Build Coastguard Worker 	    return_address_register = *readp++;
7315*7304104dSAndroid Build Coastguard Worker 	  else
7316*7304104dSAndroid Build Coastguard Worker 	    get_uleb128 (return_address_register, readp, cieend);
7317*7304104dSAndroid Build Coastguard Worker 
7318*7304104dSAndroid Build Coastguard Worker 	  printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
7319*7304104dSAndroid Build Coastguard Worker 		  "   CIE_id:                   %" PRIu64 "\n"
7320*7304104dSAndroid Build Coastguard Worker 		  "   version:                  %u\n"
7321*7304104dSAndroid Build Coastguard Worker 		  "   augmentation:             \"%s\"\n",
7322*7304104dSAndroid Build Coastguard Worker 		  offset, (uint64_t) unit_length, (uint64_t) cie_id,
7323*7304104dSAndroid Build Coastguard Worker 		  version, augmentation);
7324*7304104dSAndroid Build Coastguard Worker 	  if (version >= 4)
7325*7304104dSAndroid Build Coastguard Worker 	    printf ("   address_size:             %u\n"
7326*7304104dSAndroid Build Coastguard Worker 		    "   segment_size:             %u\n",
7327*7304104dSAndroid Build Coastguard Worker 		    ptr_size, segment_size);
7328*7304104dSAndroid Build Coastguard Worker 	  printf ("   code_alignment_factor:    %u\n"
7329*7304104dSAndroid Build Coastguard Worker 		  "   data_alignment_factor:    %d\n"
7330*7304104dSAndroid Build Coastguard Worker 		  "   return_address_register:  %u\n",
7331*7304104dSAndroid Build Coastguard Worker 		  code_alignment_factor,
7332*7304104dSAndroid Build Coastguard Worker 		  data_alignment_factor, return_address_register);
7333*7304104dSAndroid Build Coastguard Worker 
7334*7304104dSAndroid Build Coastguard Worker 	  if (augmentation[0] == 'z')
7335*7304104dSAndroid Build Coastguard Worker 	    {
7336*7304104dSAndroid Build Coastguard Worker 	      if (cieend - readp < 1)
7337*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
7338*7304104dSAndroid Build Coastguard Worker 
7339*7304104dSAndroid Build Coastguard Worker 	      unsigned int augmentationlen;
7340*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (augmentationlen, readp, cieend);
7341*7304104dSAndroid Build Coastguard Worker 
7342*7304104dSAndroid Build Coastguard Worker 	      if (augmentationlen > (size_t) (cieend - readp))
7343*7304104dSAndroid Build Coastguard Worker 		{
7344*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("invalid augmentation length"));
7345*7304104dSAndroid Build Coastguard Worker 		  readp = cieend;
7346*7304104dSAndroid Build Coastguard Worker 		  continue;
7347*7304104dSAndroid Build Coastguard Worker 		}
7348*7304104dSAndroid Build Coastguard Worker 
7349*7304104dSAndroid Build Coastguard Worker 	      const char *hdr = "Augmentation data:";
7350*7304104dSAndroid Build Coastguard Worker 	      const char *cp = augmentation + 1;
7351*7304104dSAndroid Build Coastguard Worker 	      while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
7352*7304104dSAndroid Build Coastguard Worker 		{
7353*7304104dSAndroid Build Coastguard Worker 		  printf ("   %-26s%#x ", hdr, *readp);
7354*7304104dSAndroid Build Coastguard Worker 		  hdr = "";
7355*7304104dSAndroid Build Coastguard Worker 
7356*7304104dSAndroid Build Coastguard Worker 		  if (*cp == 'R')
7357*7304104dSAndroid Build Coastguard Worker 		    {
7358*7304104dSAndroid Build Coastguard Worker 		      fde_encoding = *readp++;
7359*7304104dSAndroid Build Coastguard Worker 		      print_encoding_base (_("FDE address encoding: "),
7360*7304104dSAndroid Build Coastguard Worker 					   fde_encoding);
7361*7304104dSAndroid Build Coastguard Worker 		    }
7362*7304104dSAndroid Build Coastguard Worker 		  else if (*cp == 'L')
7363*7304104dSAndroid Build Coastguard Worker 		    {
7364*7304104dSAndroid Build Coastguard Worker 		      lsda_encoding = *readp++;
7365*7304104dSAndroid Build Coastguard Worker 		      print_encoding_base (_("LSDA pointer encoding: "),
7366*7304104dSAndroid Build Coastguard Worker 					   lsda_encoding);
7367*7304104dSAndroid Build Coastguard Worker 		    }
7368*7304104dSAndroid Build Coastguard Worker 		  else if (*cp == 'P')
7369*7304104dSAndroid Build Coastguard Worker 		    {
7370*7304104dSAndroid Build Coastguard Worker 		      /* Personality.  This field usually has a relocation
7371*7304104dSAndroid Build Coastguard Worker 			 attached pointing to __gcc_personality_v0.  */
7372*7304104dSAndroid Build Coastguard Worker 		      const unsigned char *startp = readp;
7373*7304104dSAndroid Build Coastguard Worker 		      unsigned int encoding = *readp++;
7374*7304104dSAndroid Build Coastguard Worker 		      uint64_t val = 0;
7375*7304104dSAndroid Build Coastguard Worker 		      readp = read_encoded (encoding, readp,
7376*7304104dSAndroid Build Coastguard Worker 					    readp - 1 + augmentationlen,
7377*7304104dSAndroid Build Coastguard Worker 					    &val, dbg);
7378*7304104dSAndroid Build Coastguard Worker 
7379*7304104dSAndroid Build Coastguard Worker 		      while (++startp < readp)
7380*7304104dSAndroid Build Coastguard Worker 			printf ("%#x ", *startp);
7381*7304104dSAndroid Build Coastguard Worker 
7382*7304104dSAndroid Build Coastguard Worker 		      putchar ('(');
7383*7304104dSAndroid Build Coastguard Worker 		      print_encoding (encoding);
7384*7304104dSAndroid Build Coastguard Worker 		      putchar (' ');
7385*7304104dSAndroid Build Coastguard Worker 		      switch (encoding & 0xf)
7386*7304104dSAndroid Build Coastguard Worker 			{
7387*7304104dSAndroid Build Coastguard Worker 			case DW_EH_PE_sleb128:
7388*7304104dSAndroid Build Coastguard Worker 			case DW_EH_PE_sdata2:
7389*7304104dSAndroid Build Coastguard Worker 			case DW_EH_PE_sdata4:
7390*7304104dSAndroid Build Coastguard Worker 			  printf ("%" PRId64 ")\n", val);
7391*7304104dSAndroid Build Coastguard Worker 			  break;
7392*7304104dSAndroid Build Coastguard Worker 			default:
7393*7304104dSAndroid Build Coastguard Worker 			  printf ("%#" PRIx64 ")\n", val);
7394*7304104dSAndroid Build Coastguard Worker 			  break;
7395*7304104dSAndroid Build Coastguard Worker 			}
7396*7304104dSAndroid Build Coastguard Worker 		    }
7397*7304104dSAndroid Build Coastguard Worker 		  else
7398*7304104dSAndroid Build Coastguard Worker 		    printf ("(%x)\n", *readp++);
7399*7304104dSAndroid Build Coastguard Worker 
7400*7304104dSAndroid Build Coastguard Worker 		  ++cp;
7401*7304104dSAndroid Build Coastguard Worker 		}
7402*7304104dSAndroid Build Coastguard Worker 	    }
7403*7304104dSAndroid Build Coastguard Worker 
7404*7304104dSAndroid Build Coastguard Worker 	  if (likely (ptr_size == 4 || ptr_size == 8))
7405*7304104dSAndroid Build Coastguard Worker 	    {
7406*7304104dSAndroid Build Coastguard Worker 	      struct cieinfo *newp = alloca (sizeof (*newp));
7407*7304104dSAndroid Build Coastguard Worker 	      newp->cie_offset = offset;
7408*7304104dSAndroid Build Coastguard Worker 	      newp->augmentation = augmentation;
7409*7304104dSAndroid Build Coastguard Worker 	      newp->fde_encoding = fde_encoding;
7410*7304104dSAndroid Build Coastguard Worker 	      newp->lsda_encoding = lsda_encoding;
7411*7304104dSAndroid Build Coastguard Worker 	      newp->address_size = ptr_size;
7412*7304104dSAndroid Build Coastguard Worker 	      newp->code_alignment_factor = code_alignment_factor;
7413*7304104dSAndroid Build Coastguard Worker 	      newp->data_alignment_factor = data_alignment_factor;
7414*7304104dSAndroid Build Coastguard Worker 	      newp->next = cies;
7415*7304104dSAndroid Build Coastguard Worker 	      cies = newp;
7416*7304104dSAndroid Build Coastguard Worker 	    }
7417*7304104dSAndroid Build Coastguard Worker 	}
7418*7304104dSAndroid Build Coastguard Worker       else
7419*7304104dSAndroid Build Coastguard Worker 	{
7420*7304104dSAndroid Build Coastguard Worker 	  struct cieinfo *cie = cies;
7421*7304104dSAndroid Build Coastguard Worker 	  while (cie != NULL)
7422*7304104dSAndroid Build Coastguard Worker 	    if (is_eh_frame
7423*7304104dSAndroid Build Coastguard Worker 		? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
7424*7304104dSAndroid Build Coastguard Worker 		: cie_id == (Dwarf_Off) cie->cie_offset)
7425*7304104dSAndroid Build Coastguard Worker 	      break;
7426*7304104dSAndroid Build Coastguard Worker 	    else
7427*7304104dSAndroid Build Coastguard Worker 	      cie = cie->next;
7428*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (cie == NULL))
7429*7304104dSAndroid Build Coastguard Worker 	    {
7430*7304104dSAndroid Build Coastguard Worker 	      puts ("invalid CIE reference in FDE");
7431*7304104dSAndroid Build Coastguard Worker 	      return;
7432*7304104dSAndroid Build Coastguard Worker 	    }
7433*7304104dSAndroid Build Coastguard Worker 
7434*7304104dSAndroid Build Coastguard Worker 	  /* Initialize from CIE data.  */
7435*7304104dSAndroid Build Coastguard Worker 	  fde_encoding = cie->fde_encoding;
7436*7304104dSAndroid Build Coastguard Worker 	  lsda_encoding = cie->lsda_encoding;
7437*7304104dSAndroid Build Coastguard Worker 	  ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
7438*7304104dSAndroid Build Coastguard Worker 	  code_alignment_factor = cie->code_alignment_factor;
7439*7304104dSAndroid Build Coastguard Worker 	  data_alignment_factor = cie->data_alignment_factor;
7440*7304104dSAndroid Build Coastguard Worker 
7441*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *base = readp;
7442*7304104dSAndroid Build Coastguard Worker 	  // XXX There are sometimes relocations for this value
7443*7304104dSAndroid Build Coastguard Worker 	  initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
7444*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word address_range
7445*7304104dSAndroid Build Coastguard Worker 	    = read_addr_unaligned_inc (ptr_size, dbg, readp);
7446*7304104dSAndroid Build Coastguard Worker 
7447*7304104dSAndroid Build Coastguard Worker 	  /* pcrel for an FDE address is relative to the runtime
7448*7304104dSAndroid Build Coastguard Worker 	     address of the start_address field itself.  Sign extend
7449*7304104dSAndroid Build Coastguard Worker 	     if necessary to make sure the calculation is done on the
7450*7304104dSAndroid Build Coastguard Worker 	     full 64 bit address even when initial_location only holds
7451*7304104dSAndroid Build Coastguard Worker 	     the lower 32 bits.  */
7452*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Addr pc_start = initial_location;
7453*7304104dSAndroid Build Coastguard Worker 	  if (ptr_size == 4)
7454*7304104dSAndroid Build Coastguard Worker 	    pc_start = (uint64_t) (int32_t) pc_start;
7455*7304104dSAndroid Build Coastguard Worker 	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
7456*7304104dSAndroid Build Coastguard Worker 	    pc_start += ((uint64_t) shdr->sh_addr
7457*7304104dSAndroid Build Coastguard Worker 			 + (base - (const unsigned char *) data->d_buf)
7458*7304104dSAndroid Build Coastguard Worker 			 - bias);
7459*7304104dSAndroid Build Coastguard Worker 
7460*7304104dSAndroid Build Coastguard Worker 	  printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
7461*7304104dSAndroid Build Coastguard Worker 		  "   CIE_pointer:              %" PRIu64 "\n"
7462*7304104dSAndroid Build Coastguard Worker 		  "   initial_location:         ",
7463*7304104dSAndroid Build Coastguard Worker 		  offset, (uint64_t) unit_length,
7464*7304104dSAndroid Build Coastguard Worker 		  cie->cie_offset, (uint64_t) cie_id);
7465*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, cie->address_size,
7466*7304104dSAndroid Build Coastguard Worker 			    pc_start, initial_location);
7467*7304104dSAndroid Build Coastguard Worker 	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
7468*7304104dSAndroid Build Coastguard Worker 	    {
7469*7304104dSAndroid Build Coastguard Worker 	      vma_base = (((uint64_t) shdr->sh_offset
7470*7304104dSAndroid Build Coastguard Worker 			   + (base - (const unsigned char *) data->d_buf)
7471*7304104dSAndroid Build Coastguard Worker 			   + (uint64_t) initial_location)
7472*7304104dSAndroid Build Coastguard Worker 			  & (ptr_size == 4
7473*7304104dSAndroid Build Coastguard Worker 			     ? UINT64_C (0xffffffff)
7474*7304104dSAndroid Build Coastguard Worker 			     : UINT64_C (0xffffffffffffffff)));
7475*7304104dSAndroid Build Coastguard Worker 	      printf (_(" (offset: %#" PRIx64 ")"),
7476*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) vma_base);
7477*7304104dSAndroid Build Coastguard Worker 	    }
7478*7304104dSAndroid Build Coastguard Worker 
7479*7304104dSAndroid Build Coastguard Worker 	  printf ("\n   address_range:            %#" PRIx64,
7480*7304104dSAndroid Build Coastguard Worker 		  (uint64_t) address_range);
7481*7304104dSAndroid Build Coastguard Worker 	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
7482*7304104dSAndroid Build Coastguard Worker 	    printf (_(" (end offset: %#" PRIx64 ")"),
7483*7304104dSAndroid Build Coastguard Worker 		    ((uint64_t) vma_base + (uint64_t) address_range)
7484*7304104dSAndroid Build Coastguard Worker 		    & (ptr_size == 4
7485*7304104dSAndroid Build Coastguard Worker 		       ? UINT64_C (0xffffffff)
7486*7304104dSAndroid Build Coastguard Worker 		       : UINT64_C (0xffffffffffffffff)));
7487*7304104dSAndroid Build Coastguard Worker 	  putchar ('\n');
7488*7304104dSAndroid Build Coastguard Worker 
7489*7304104dSAndroid Build Coastguard Worker 	  if (cie->augmentation[0] == 'z')
7490*7304104dSAndroid Build Coastguard Worker 	    {
7491*7304104dSAndroid Build Coastguard Worker 	      unsigned int augmentationlen;
7492*7304104dSAndroid Build Coastguard Worker 	      if (cieend - readp < 1)
7493*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
7494*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (augmentationlen, readp, cieend);
7495*7304104dSAndroid Build Coastguard Worker 
7496*7304104dSAndroid Build Coastguard Worker 	      if (augmentationlen > (size_t) (cieend - readp))
7497*7304104dSAndroid Build Coastguard Worker 		{
7498*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("invalid augmentation length"));
7499*7304104dSAndroid Build Coastguard Worker 		  readp = cieend;
7500*7304104dSAndroid Build Coastguard Worker 		  continue;
7501*7304104dSAndroid Build Coastguard Worker 		}
7502*7304104dSAndroid Build Coastguard Worker 
7503*7304104dSAndroid Build Coastguard Worker 	      if (augmentationlen > 0)
7504*7304104dSAndroid Build Coastguard Worker 		{
7505*7304104dSAndroid Build Coastguard Worker 		  const char *hdr = "Augmentation data:";
7506*7304104dSAndroid Build Coastguard Worker 		  const char *cp = cie->augmentation + 1;
7507*7304104dSAndroid Build Coastguard Worker 		  unsigned int u = 0;
7508*7304104dSAndroid Build Coastguard Worker 		  while (*cp != '\0'
7509*7304104dSAndroid Build Coastguard Worker 			 && cp < cie->augmentation + augmentationlen + 1)
7510*7304104dSAndroid Build Coastguard Worker 		    {
7511*7304104dSAndroid Build Coastguard Worker 		      if (*cp == 'L')
7512*7304104dSAndroid Build Coastguard Worker 			{
7513*7304104dSAndroid Build Coastguard Worker 			  uint64_t lsda_pointer;
7514*7304104dSAndroid Build Coastguard Worker 			  const unsigned char *p
7515*7304104dSAndroid Build Coastguard Worker 			    = read_encoded (lsda_encoding, &readp[u],
7516*7304104dSAndroid Build Coastguard Worker 					    &readp[augmentationlen],
7517*7304104dSAndroid Build Coastguard Worker 					    &lsda_pointer, dbg);
7518*7304104dSAndroid Build Coastguard Worker 			  u = p - readp;
7519*7304104dSAndroid Build Coastguard Worker 			  printf (_("\
7520*7304104dSAndroid Build Coastguard Worker    %-26sLSDA pointer: %#" PRIx64 "\n"),
7521*7304104dSAndroid Build Coastguard Worker 				  hdr, lsda_pointer);
7522*7304104dSAndroid Build Coastguard Worker 			  hdr = "";
7523*7304104dSAndroid Build Coastguard Worker 			}
7524*7304104dSAndroid Build Coastguard Worker 		      ++cp;
7525*7304104dSAndroid Build Coastguard Worker 		    }
7526*7304104dSAndroid Build Coastguard Worker 
7527*7304104dSAndroid Build Coastguard Worker 		  while (u < augmentationlen)
7528*7304104dSAndroid Build Coastguard Worker 		    {
7529*7304104dSAndroid Build Coastguard Worker 		      printf ("   %-26s%#x\n", hdr, readp[u++]);
7530*7304104dSAndroid Build Coastguard Worker 		      hdr = "";
7531*7304104dSAndroid Build Coastguard Worker 		    }
7532*7304104dSAndroid Build Coastguard Worker 		}
7533*7304104dSAndroid Build Coastguard Worker 
7534*7304104dSAndroid Build Coastguard Worker 	      readp += augmentationlen;
7535*7304104dSAndroid Build Coastguard Worker 	    }
7536*7304104dSAndroid Build Coastguard Worker 	}
7537*7304104dSAndroid Build Coastguard Worker 
7538*7304104dSAndroid Build Coastguard Worker       /* Handle the initialization instructions.  */
7539*7304104dSAndroid Build Coastguard Worker       if (ptr_size != 4 && ptr_size !=8)
7540*7304104dSAndroid Build Coastguard Worker 	printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
7541*7304104dSAndroid Build Coastguard Worker       else
7542*7304104dSAndroid Build Coastguard Worker 	print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
7543*7304104dSAndroid Build Coastguard Worker 			   data_alignment_factor, version, ptr_size,
7544*7304104dSAndroid Build Coastguard Worker 			   fde_encoding, dwflmod, ebl, ehdr, dbg);
7545*7304104dSAndroid Build Coastguard Worker       readp = cieend;
7546*7304104dSAndroid Build Coastguard Worker     }
7547*7304104dSAndroid Build Coastguard Worker }
7548*7304104dSAndroid Build Coastguard Worker 
7549*7304104dSAndroid Build Coastguard Worker 
7550*7304104dSAndroid Build Coastguard Worker /* Returns the signedness (or false if it cannot be determined) and
7551*7304104dSAndroid Build Coastguard Worker    the byte size (or zero if it cannot be gotten) of the given DIE
7552*7304104dSAndroid Build Coastguard Worker    DW_AT_type attribute.  Uses dwarf_peel_type and dwarf_aggregate_size.  */
7553*7304104dSAndroid Build Coastguard Worker static void
die_type_sign_bytes(Dwarf_Die * die,bool * is_signed,int * bytes)7554*7304104dSAndroid Build Coastguard Worker die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
7555*7304104dSAndroid Build Coastguard Worker {
7556*7304104dSAndroid Build Coastguard Worker   Dwarf_Attribute attr;
7557*7304104dSAndroid Build Coastguard Worker   Dwarf_Die type;
7558*7304104dSAndroid Build Coastguard Worker 
7559*7304104dSAndroid Build Coastguard Worker   *bytes = 0;
7560*7304104dSAndroid Build Coastguard Worker   *is_signed = false;
7561*7304104dSAndroid Build Coastguard Worker 
7562*7304104dSAndroid Build Coastguard Worker   if (dwarf_peel_type (dwarf_formref_die (dwarf_attr_integrate (die,
7563*7304104dSAndroid Build Coastguard Worker 								DW_AT_type,
7564*7304104dSAndroid Build Coastguard Worker 								&attr), &type),
7565*7304104dSAndroid Build Coastguard Worker 		       &type) == 0)
7566*7304104dSAndroid Build Coastguard Worker     {
7567*7304104dSAndroid Build Coastguard Worker       Dwarf_Word val;
7568*7304104dSAndroid Build Coastguard Worker       *is_signed = (dwarf_formudata (dwarf_attr (&type, DW_AT_encoding,
7569*7304104dSAndroid Build Coastguard Worker 						 &attr), &val) == 0
7570*7304104dSAndroid Build Coastguard Worker 		    && (val == DW_ATE_signed || val == DW_ATE_signed_char));
7571*7304104dSAndroid Build Coastguard Worker 
7572*7304104dSAndroid Build Coastguard Worker       if (dwarf_aggregate_size (&type, &val) == 0)
7573*7304104dSAndroid Build Coastguard Worker 	*bytes = val;
7574*7304104dSAndroid Build Coastguard Worker     }
7575*7304104dSAndroid Build Coastguard Worker }
7576*7304104dSAndroid Build Coastguard Worker 
7577*7304104dSAndroid Build Coastguard Worker struct attrcb_args
7578*7304104dSAndroid Build Coastguard Worker {
7579*7304104dSAndroid Build Coastguard Worker   Dwfl_Module *dwflmod;
7580*7304104dSAndroid Build Coastguard Worker   Dwarf *dbg;
7581*7304104dSAndroid Build Coastguard Worker   Dwarf_Die *dies;
7582*7304104dSAndroid Build Coastguard Worker   int level;
7583*7304104dSAndroid Build Coastguard Worker   bool silent;
7584*7304104dSAndroid Build Coastguard Worker   bool is_split;
7585*7304104dSAndroid Build Coastguard Worker   unsigned int version;
7586*7304104dSAndroid Build Coastguard Worker   unsigned int addrsize;
7587*7304104dSAndroid Build Coastguard Worker   unsigned int offset_size;
7588*7304104dSAndroid Build Coastguard Worker   struct Dwarf_CU *cu;
7589*7304104dSAndroid Build Coastguard Worker };
7590*7304104dSAndroid Build Coastguard Worker 
7591*7304104dSAndroid Build Coastguard Worker 
7592*7304104dSAndroid Build Coastguard Worker static int
attr_callback(Dwarf_Attribute * attrp,void * arg)7593*7304104dSAndroid Build Coastguard Worker attr_callback (Dwarf_Attribute *attrp, void *arg)
7594*7304104dSAndroid Build Coastguard Worker {
7595*7304104dSAndroid Build Coastguard Worker   struct attrcb_args *cbargs = (struct attrcb_args *) arg;
7596*7304104dSAndroid Build Coastguard Worker   const int level = cbargs->level;
7597*7304104dSAndroid Build Coastguard Worker   Dwarf_Die *die = &cbargs->dies[level];
7598*7304104dSAndroid Build Coastguard Worker   bool is_split = cbargs->is_split;
7599*7304104dSAndroid Build Coastguard Worker 
7600*7304104dSAndroid Build Coastguard Worker   unsigned int attr = dwarf_whatattr (attrp);
7601*7304104dSAndroid Build Coastguard Worker   if (unlikely (attr == 0))
7602*7304104dSAndroid Build Coastguard Worker     {
7603*7304104dSAndroid Build Coastguard Worker       if (!cbargs->silent)
7604*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("DIE [%" PRIx64 "] "
7605*7304104dSAndroid Build Coastguard Worker 			      "cannot get attribute code: %s"),
7606*7304104dSAndroid Build Coastguard Worker 	       dwarf_dieoffset (die), dwarf_errmsg (-1));
7607*7304104dSAndroid Build Coastguard Worker       return DWARF_CB_ABORT;
7608*7304104dSAndroid Build Coastguard Worker     }
7609*7304104dSAndroid Build Coastguard Worker 
7610*7304104dSAndroid Build Coastguard Worker   unsigned int form = dwarf_whatform (attrp);
7611*7304104dSAndroid Build Coastguard Worker   if (unlikely (form == 0))
7612*7304104dSAndroid Build Coastguard Worker     {
7613*7304104dSAndroid Build Coastguard Worker       if (!cbargs->silent)
7614*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("DIE [%" PRIx64 "] "
7615*7304104dSAndroid Build Coastguard Worker 			      "cannot get attribute form: %s"),
7616*7304104dSAndroid Build Coastguard Worker 	       dwarf_dieoffset (die), dwarf_errmsg (-1));
7617*7304104dSAndroid Build Coastguard Worker       return DWARF_CB_ABORT;
7618*7304104dSAndroid Build Coastguard Worker     }
7619*7304104dSAndroid Build Coastguard Worker 
7620*7304104dSAndroid Build Coastguard Worker   switch (form)
7621*7304104dSAndroid Build Coastguard Worker     {
7622*7304104dSAndroid Build Coastguard Worker     case DW_FORM_addr:
7623*7304104dSAndroid Build Coastguard Worker     case DW_FORM_addrx:
7624*7304104dSAndroid Build Coastguard Worker     case DW_FORM_addrx1:
7625*7304104dSAndroid Build Coastguard Worker     case DW_FORM_addrx2:
7626*7304104dSAndroid Build Coastguard Worker     case DW_FORM_addrx3:
7627*7304104dSAndroid Build Coastguard Worker     case DW_FORM_addrx4:
7628*7304104dSAndroid Build Coastguard Worker     case DW_FORM_GNU_addr_index:
7629*7304104dSAndroid Build Coastguard Worker       if (!cbargs->silent)
7630*7304104dSAndroid Build Coastguard Worker 	{
7631*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Addr addr;
7632*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
7633*7304104dSAndroid Build Coastguard Worker 	    {
7634*7304104dSAndroid Build Coastguard Worker 	    attrval_out:
7635*7304104dSAndroid Build Coastguard Worker 	      if (!cbargs->silent)
7636*7304104dSAndroid Build Coastguard Worker 		error (0, 0, _("DIE [%" PRIx64 "] "
7637*7304104dSAndroid Build Coastguard Worker 				      "cannot get attribute '%s' (%s) value: "
7638*7304104dSAndroid Build Coastguard Worker 				      "%s"),
7639*7304104dSAndroid Build Coastguard Worker 		       dwarf_dieoffset (die),
7640*7304104dSAndroid Build Coastguard Worker 		       dwarf_attr_name (attr),
7641*7304104dSAndroid Build Coastguard Worker 		       dwarf_form_name (form),
7642*7304104dSAndroid Build Coastguard Worker 		       dwarf_errmsg (-1));
7643*7304104dSAndroid Build Coastguard Worker 	      /* Don't ABORT, it might be other attributes can be resolved.  */
7644*7304104dSAndroid Build Coastguard Worker 	      return DWARF_CB_OK;
7645*7304104dSAndroid Build Coastguard Worker 	    }
7646*7304104dSAndroid Build Coastguard Worker 	  if (form != DW_FORM_addr )
7647*7304104dSAndroid Build Coastguard Worker 	    {
7648*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Word word;
7649*7304104dSAndroid Build Coastguard Worker 	      if (dwarf_formudata (attrp, &word) != 0)
7650*7304104dSAndroid Build Coastguard Worker 		goto attrval_out;
7651*7304104dSAndroid Build Coastguard Worker 	      printf ("           %*s%-20s (%s) [%" PRIx64 "] ",
7652*7304104dSAndroid Build Coastguard Worker 		      (int) (level * 2), "", dwarf_attr_name (attr),
7653*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form), word);
7654*7304104dSAndroid Build Coastguard Worker 	    }
7655*7304104dSAndroid Build Coastguard Worker 	  else
7656*7304104dSAndroid Build Coastguard Worker 	    printf ("           %*s%-20s (%s) ",
7657*7304104dSAndroid Build Coastguard Worker 		    (int) (level * 2), "", dwarf_attr_name (attr),
7658*7304104dSAndroid Build Coastguard Worker 		    dwarf_form_name (form));
7659*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
7660*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
7661*7304104dSAndroid Build Coastguard Worker 	}
7662*7304104dSAndroid Build Coastguard Worker       break;
7663*7304104dSAndroid Build Coastguard Worker 
7664*7304104dSAndroid Build Coastguard Worker     case DW_FORM_indirect:
7665*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strp:
7666*7304104dSAndroid Build Coastguard Worker     case DW_FORM_line_strp:
7667*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx:
7668*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx1:
7669*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx2:
7670*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx3:
7671*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx4:
7672*7304104dSAndroid Build Coastguard Worker     case DW_FORM_string:
7673*7304104dSAndroid Build Coastguard Worker     case DW_FORM_GNU_strp_alt:
7674*7304104dSAndroid Build Coastguard Worker     case DW_FORM_GNU_str_index:
7675*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
7676*7304104dSAndroid Build Coastguard Worker 	break;
7677*7304104dSAndroid Build Coastguard Worker       const char *str = dwarf_formstring (attrp);
7678*7304104dSAndroid Build Coastguard Worker       if (unlikely (str == NULL))
7679*7304104dSAndroid Build Coastguard Worker 	goto attrval_out;
7680*7304104dSAndroid Build Coastguard Worker       printf ("           %*s%-20s (%s) \"%s\"\n",
7681*7304104dSAndroid Build Coastguard Worker 	      (int) (level * 2), "", dwarf_attr_name (attr),
7682*7304104dSAndroid Build Coastguard Worker 	      dwarf_form_name (form), str);
7683*7304104dSAndroid Build Coastguard Worker       break;
7684*7304104dSAndroid Build Coastguard Worker 
7685*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref_addr:
7686*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref_udata:
7687*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref8:
7688*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref4:
7689*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref2:
7690*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref1:
7691*7304104dSAndroid Build Coastguard Worker     case DW_FORM_GNU_ref_alt:
7692*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref_sup4:
7693*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref_sup8:
7694*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
7695*7304104dSAndroid Build Coastguard Worker 	break;
7696*7304104dSAndroid Build Coastguard Worker       Dwarf_Die ref;
7697*7304104dSAndroid Build Coastguard Worker       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
7698*7304104dSAndroid Build Coastguard Worker 	goto attrval_out;
7699*7304104dSAndroid Build Coastguard Worker 
7700*7304104dSAndroid Build Coastguard Worker       printf ("           %*s%-20s (%s) ",
7701*7304104dSAndroid Build Coastguard Worker 	      (int) (level * 2), "", dwarf_attr_name (attr),
7702*7304104dSAndroid Build Coastguard Worker 	      dwarf_form_name (form));
7703*7304104dSAndroid Build Coastguard Worker       if (is_split)
7704*7304104dSAndroid Build Coastguard Worker 	printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
7705*7304104dSAndroid Build Coastguard Worker       else
7706*7304104dSAndroid Build Coastguard Worker 	printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
7707*7304104dSAndroid Build Coastguard Worker       break;
7708*7304104dSAndroid Build Coastguard Worker 
7709*7304104dSAndroid Build Coastguard Worker     case DW_FORM_ref_sig8:
7710*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
7711*7304104dSAndroid Build Coastguard Worker 	break;
7712*7304104dSAndroid Build Coastguard Worker       printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
7713*7304104dSAndroid Build Coastguard Worker 	      (int) (level * 2), "", dwarf_attr_name (attr),
7714*7304104dSAndroid Build Coastguard Worker 	      dwarf_form_name (form),
7715*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
7716*7304104dSAndroid Build Coastguard Worker       break;
7717*7304104dSAndroid Build Coastguard Worker 
7718*7304104dSAndroid Build Coastguard Worker     case DW_FORM_sec_offset:
7719*7304104dSAndroid Build Coastguard Worker     case DW_FORM_rnglistx:
7720*7304104dSAndroid Build Coastguard Worker     case DW_FORM_loclistx:
7721*7304104dSAndroid Build Coastguard Worker     case DW_FORM_implicit_const:
7722*7304104dSAndroid Build Coastguard Worker     case DW_FORM_udata:
7723*7304104dSAndroid Build Coastguard Worker     case DW_FORM_sdata:
7724*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data8: /* Note no data16 here, we see that as block. */
7725*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data4:
7726*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data2:
7727*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data1:;
7728*7304104dSAndroid Build Coastguard Worker       Dwarf_Word num;
7729*7304104dSAndroid Build Coastguard Worker       if (unlikely (dwarf_formudata (attrp, &num) != 0))
7730*7304104dSAndroid Build Coastguard Worker 	goto attrval_out;
7731*7304104dSAndroid Build Coastguard Worker 
7732*7304104dSAndroid Build Coastguard Worker       const char *valuestr = NULL;
7733*7304104dSAndroid Build Coastguard Worker       bool as_hex_id = false;
7734*7304104dSAndroid Build Coastguard Worker       switch (attr)
7735*7304104dSAndroid Build Coastguard Worker 	{
7736*7304104dSAndroid Build Coastguard Worker 	  /* This case can take either a constant or a loclistptr.  */
7737*7304104dSAndroid Build Coastguard Worker 	case DW_AT_data_member_location:
7738*7304104dSAndroid Build Coastguard Worker 	  if (form != DW_FORM_sec_offset
7739*7304104dSAndroid Build Coastguard Worker 	      && (cbargs->version >= 4
7740*7304104dSAndroid Build Coastguard Worker 		  || (form != DW_FORM_data4 && form != DW_FORM_data8)))
7741*7304104dSAndroid Build Coastguard Worker 	    {
7742*7304104dSAndroid Build Coastguard Worker 	      if (!cbargs->silent)
7743*7304104dSAndroid Build Coastguard Worker 		printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
7744*7304104dSAndroid Build Coastguard Worker 			(int) (level * 2), "", dwarf_attr_name (attr),
7745*7304104dSAndroid Build Coastguard Worker 			dwarf_form_name (form), (uintmax_t) num);
7746*7304104dSAndroid Build Coastguard Worker 	      return DWARF_CB_OK;
7747*7304104dSAndroid Build Coastguard Worker 	    }
7748*7304104dSAndroid Build Coastguard Worker 	  FALLTHROUGH;
7749*7304104dSAndroid Build Coastguard Worker 
7750*7304104dSAndroid Build Coastguard Worker 	/* These cases always take a loclist[ptr] and no constant. */
7751*7304104dSAndroid Build Coastguard Worker 	case DW_AT_location:
7752*7304104dSAndroid Build Coastguard Worker 	case DW_AT_data_location:
7753*7304104dSAndroid Build Coastguard Worker 	case DW_AT_vtable_elem_location:
7754*7304104dSAndroid Build Coastguard Worker 	case DW_AT_string_length:
7755*7304104dSAndroid Build Coastguard Worker 	case DW_AT_use_location:
7756*7304104dSAndroid Build Coastguard Worker 	case DW_AT_frame_base:
7757*7304104dSAndroid Build Coastguard Worker 	case DW_AT_return_addr:
7758*7304104dSAndroid Build Coastguard Worker 	case DW_AT_static_link:
7759*7304104dSAndroid Build Coastguard Worker 	case DW_AT_segment:
7760*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_value:
7761*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_data_value:
7762*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_target:
7763*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_target_clobbered:
7764*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_locviews:
7765*7304104dSAndroid Build Coastguard Worker 	  {
7766*7304104dSAndroid Build Coastguard Worker 	    bool nlpt;
7767*7304104dSAndroid Build Coastguard Worker 	    if (cbargs->cu->version < 5)
7768*7304104dSAndroid Build Coastguard Worker 	      {
7769*7304104dSAndroid Build Coastguard Worker 		if (! cbargs->is_split)
7770*7304104dSAndroid Build Coastguard Worker 		  {
7771*7304104dSAndroid Build Coastguard Worker 		    nlpt = notice_listptr (section_loc, &known_locsptr,
7772*7304104dSAndroid Build Coastguard Worker 					   cbargs->addrsize,
7773*7304104dSAndroid Build Coastguard Worker 					   cbargs->offset_size,
7774*7304104dSAndroid Build Coastguard Worker 					   cbargs->cu, num, attr);
7775*7304104dSAndroid Build Coastguard Worker 		  }
7776*7304104dSAndroid Build Coastguard Worker 		else
7777*7304104dSAndroid Build Coastguard Worker 		  nlpt = true;
7778*7304104dSAndroid Build Coastguard Worker 	      }
7779*7304104dSAndroid Build Coastguard Worker 	    else
7780*7304104dSAndroid Build Coastguard Worker 	      {
7781*7304104dSAndroid Build Coastguard Worker 		/* Only register for a real section offset.  Otherwise
7782*7304104dSAndroid Build Coastguard Worker 		   it is a DW_FORM_loclistx which is just an index
7783*7304104dSAndroid Build Coastguard Worker 		   number and we should already have registered the
7784*7304104dSAndroid Build Coastguard Worker 		   section offset for the index when we saw the
7785*7304104dSAndroid Build Coastguard Worker 		   DW_AT_loclists_base CU attribute.  */
7786*7304104dSAndroid Build Coastguard Worker 		if (form == DW_FORM_sec_offset)
7787*7304104dSAndroid Build Coastguard Worker 		  nlpt = notice_listptr (section_loc, &known_loclistsptr,
7788*7304104dSAndroid Build Coastguard Worker 					 cbargs->addrsize, cbargs->offset_size,
7789*7304104dSAndroid Build Coastguard Worker 					 cbargs->cu, num, attr);
7790*7304104dSAndroid Build Coastguard Worker 		else
7791*7304104dSAndroid Build Coastguard Worker 		  nlpt = true;
7792*7304104dSAndroid Build Coastguard Worker 
7793*7304104dSAndroid Build Coastguard Worker 	      }
7794*7304104dSAndroid Build Coastguard Worker 
7795*7304104dSAndroid Build Coastguard Worker 	    if (!cbargs->silent)
7796*7304104dSAndroid Build Coastguard Worker 	      {
7797*7304104dSAndroid Build Coastguard Worker 		if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7798*7304104dSAndroid Build Coastguard Worker 		  printf ("           %*s%-20s (%s) location list [%6"
7799*7304104dSAndroid Build Coastguard Worker 			  PRIxMAX "]%s\n",
7800*7304104dSAndroid Build Coastguard Worker 			  (int) (level * 2), "", dwarf_attr_name (attr),
7801*7304104dSAndroid Build Coastguard Worker 			  dwarf_form_name (form), (uintmax_t) num,
7802*7304104dSAndroid Build Coastguard Worker 			  nlpt ? "" : " <WARNING offset too big>");
7803*7304104dSAndroid Build Coastguard Worker 		else
7804*7304104dSAndroid Build Coastguard Worker 		  printf ("           %*s%-20s (%s) location index [%6"
7805*7304104dSAndroid Build Coastguard Worker 			  PRIxMAX "]\n",
7806*7304104dSAndroid Build Coastguard Worker 			  (int) (level * 2), "", dwarf_attr_name (attr),
7807*7304104dSAndroid Build Coastguard Worker 			  dwarf_form_name (form), (uintmax_t) num);
7808*7304104dSAndroid Build Coastguard Worker 	      }
7809*7304104dSAndroid Build Coastguard Worker 	  }
7810*7304104dSAndroid Build Coastguard Worker 	  return DWARF_CB_OK;
7811*7304104dSAndroid Build Coastguard Worker 
7812*7304104dSAndroid Build Coastguard Worker 	case DW_AT_loclists_base:
7813*7304104dSAndroid Build Coastguard Worker 	  {
7814*7304104dSAndroid Build Coastguard Worker 	    bool nlpt = notice_listptr (section_loc, &known_loclistsptr,
7815*7304104dSAndroid Build Coastguard Worker                                         cbargs->addrsize, cbargs->offset_size,
7816*7304104dSAndroid Build Coastguard Worker                                         cbargs->cu, num, attr);
7817*7304104dSAndroid Build Coastguard Worker 
7818*7304104dSAndroid Build Coastguard Worker 	    if (!cbargs->silent)
7819*7304104dSAndroid Build Coastguard Worker 	      printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
7820*7304104dSAndroid Build Coastguard Worker 		      (int) (level * 2), "", dwarf_attr_name (attr),
7821*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form), (uintmax_t) num,
7822*7304104dSAndroid Build Coastguard Worker 		      nlpt ? "" : " <WARNING offset too big>");
7823*7304104dSAndroid Build Coastguard Worker 	  }
7824*7304104dSAndroid Build Coastguard Worker 	  return DWARF_CB_OK;
7825*7304104dSAndroid Build Coastguard Worker 
7826*7304104dSAndroid Build Coastguard Worker 	case DW_AT_ranges:
7827*7304104dSAndroid Build Coastguard Worker 	case DW_AT_start_scope:
7828*7304104dSAndroid Build Coastguard Worker 	  {
7829*7304104dSAndroid Build Coastguard Worker 	    bool nlpt;
7830*7304104dSAndroid Build Coastguard Worker 	    if (cbargs->cu->version < 5)
7831*7304104dSAndroid Build Coastguard Worker 	      nlpt = notice_listptr (section_ranges, &known_rangelistptr,
7832*7304104dSAndroid Build Coastguard Worker 				     cbargs->addrsize, cbargs->offset_size,
7833*7304104dSAndroid Build Coastguard Worker 				     cbargs->cu, num, attr);
7834*7304104dSAndroid Build Coastguard Worker 	    else
7835*7304104dSAndroid Build Coastguard Worker 	      {
7836*7304104dSAndroid Build Coastguard Worker 		/* Only register for a real section offset.  Otherwise
7837*7304104dSAndroid Build Coastguard Worker 		   it is a DW_FORM_rangelistx which is just an index
7838*7304104dSAndroid Build Coastguard Worker 		   number and we should already have registered the
7839*7304104dSAndroid Build Coastguard Worker 		   section offset for the index when we saw the
7840*7304104dSAndroid Build Coastguard Worker 		   DW_AT_rnglists_base CU attribute.  */
7841*7304104dSAndroid Build Coastguard Worker 		if (form == DW_FORM_sec_offset)
7842*7304104dSAndroid Build Coastguard Worker 		  nlpt = notice_listptr (section_ranges, &known_rnglistptr,
7843*7304104dSAndroid Build Coastguard Worker 					 cbargs->addrsize, cbargs->offset_size,
7844*7304104dSAndroid Build Coastguard Worker 					 cbargs->cu, num, attr);
7845*7304104dSAndroid Build Coastguard Worker 		else
7846*7304104dSAndroid Build Coastguard Worker 		  nlpt = true;
7847*7304104dSAndroid Build Coastguard Worker 	      }
7848*7304104dSAndroid Build Coastguard Worker 
7849*7304104dSAndroid Build Coastguard Worker 	    if (!cbargs->silent)
7850*7304104dSAndroid Build Coastguard Worker 	      {
7851*7304104dSAndroid Build Coastguard Worker 		if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
7852*7304104dSAndroid Build Coastguard Worker 		  printf ("           %*s%-20s (%s) range list [%6"
7853*7304104dSAndroid Build Coastguard Worker 			  PRIxMAX "]%s\n",
7854*7304104dSAndroid Build Coastguard Worker 			  (int) (level * 2), "", dwarf_attr_name (attr),
7855*7304104dSAndroid Build Coastguard Worker 			  dwarf_form_name (form), (uintmax_t) num,
7856*7304104dSAndroid Build Coastguard Worker 			  nlpt ? "" : " <WARNING offset too big>");
7857*7304104dSAndroid Build Coastguard Worker 		else
7858*7304104dSAndroid Build Coastguard Worker 		  printf ("           %*s%-20s (%s) range index [%6"
7859*7304104dSAndroid Build Coastguard Worker 			  PRIxMAX "]\n",
7860*7304104dSAndroid Build Coastguard Worker 			  (int) (level * 2), "", dwarf_attr_name (attr),
7861*7304104dSAndroid Build Coastguard Worker 			  dwarf_form_name (form), (uintmax_t) num);
7862*7304104dSAndroid Build Coastguard Worker 	      }
7863*7304104dSAndroid Build Coastguard Worker 	  }
7864*7304104dSAndroid Build Coastguard Worker 	  return DWARF_CB_OK;
7865*7304104dSAndroid Build Coastguard Worker 
7866*7304104dSAndroid Build Coastguard Worker 	case DW_AT_rnglists_base:
7867*7304104dSAndroid Build Coastguard Worker 	  {
7868*7304104dSAndroid Build Coastguard Worker 	    bool nlpt = notice_listptr (section_ranges, &known_rnglistptr,
7869*7304104dSAndroid Build Coastguard Worker 					cbargs->addrsize, cbargs->offset_size,
7870*7304104dSAndroid Build Coastguard Worker 					cbargs->cu, num, attr);
7871*7304104dSAndroid Build Coastguard Worker 	    if (!cbargs->silent)
7872*7304104dSAndroid Build Coastguard Worker 	      printf ("           %*s%-20s (%s) range list [%6"
7873*7304104dSAndroid Build Coastguard Worker 		      PRIxMAX "]%s\n",
7874*7304104dSAndroid Build Coastguard Worker 		      (int) (level * 2), "", dwarf_attr_name (attr),
7875*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form), (uintmax_t) num,
7876*7304104dSAndroid Build Coastguard Worker 		      nlpt ? "" : " <WARNING offset too big>");
7877*7304104dSAndroid Build Coastguard Worker 	  }
7878*7304104dSAndroid Build Coastguard Worker 	  return DWARF_CB_OK;
7879*7304104dSAndroid Build Coastguard Worker 
7880*7304104dSAndroid Build Coastguard Worker 	case DW_AT_addr_base:
7881*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_addr_base:
7882*7304104dSAndroid Build Coastguard Worker 	  {
7883*7304104dSAndroid Build Coastguard Worker 	    bool addrbase = notice_listptr (section_addr, &known_addrbases,
7884*7304104dSAndroid Build Coastguard Worker 					    cbargs->addrsize,
7885*7304104dSAndroid Build Coastguard Worker 					    cbargs->offset_size,
7886*7304104dSAndroid Build Coastguard Worker 					    cbargs->cu, num, attr);
7887*7304104dSAndroid Build Coastguard Worker 	    if (!cbargs->silent)
7888*7304104dSAndroid Build Coastguard Worker 	      printf ("           %*s%-20s (%s) address base [%6"
7889*7304104dSAndroid Build Coastguard Worker 		      PRIxMAX "]%s\n",
7890*7304104dSAndroid Build Coastguard Worker 		      (int) (level * 2), "", dwarf_attr_name (attr),
7891*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form), (uintmax_t) num,
7892*7304104dSAndroid Build Coastguard Worker 		      addrbase ? "" : " <WARNING offset too big>");
7893*7304104dSAndroid Build Coastguard Worker 	  }
7894*7304104dSAndroid Build Coastguard Worker 	  return DWARF_CB_OK;
7895*7304104dSAndroid Build Coastguard Worker 
7896*7304104dSAndroid Build Coastguard Worker 	case DW_AT_str_offsets_base:
7897*7304104dSAndroid Build Coastguard Worker 	  {
7898*7304104dSAndroid Build Coastguard Worker 	    bool stroffbase = notice_listptr (section_str, &known_stroffbases,
7899*7304104dSAndroid Build Coastguard Worker 					      cbargs->addrsize,
7900*7304104dSAndroid Build Coastguard Worker 					      cbargs->offset_size,
7901*7304104dSAndroid Build Coastguard Worker 					      cbargs->cu, num, attr);
7902*7304104dSAndroid Build Coastguard Worker 	    if (!cbargs->silent)
7903*7304104dSAndroid Build Coastguard Worker 	      printf ("           %*s%-20s (%s) str offsets base [%6"
7904*7304104dSAndroid Build Coastguard Worker 		      PRIxMAX "]%s\n",
7905*7304104dSAndroid Build Coastguard Worker 		      (int) (level * 2), "", dwarf_attr_name (attr),
7906*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form), (uintmax_t) num,
7907*7304104dSAndroid Build Coastguard Worker 		      stroffbase ? "" : " <WARNING offset too big>");
7908*7304104dSAndroid Build Coastguard Worker 	  }
7909*7304104dSAndroid Build Coastguard Worker 	  return DWARF_CB_OK;
7910*7304104dSAndroid Build Coastguard Worker 
7911*7304104dSAndroid Build Coastguard Worker 	case DW_AT_language:
7912*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_lang_name (num);
7913*7304104dSAndroid Build Coastguard Worker 	  break;
7914*7304104dSAndroid Build Coastguard Worker 	case DW_AT_encoding:
7915*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_encoding_name (num);
7916*7304104dSAndroid Build Coastguard Worker 	  break;
7917*7304104dSAndroid Build Coastguard Worker 	case DW_AT_accessibility:
7918*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_access_name (num);
7919*7304104dSAndroid Build Coastguard Worker 	  break;
7920*7304104dSAndroid Build Coastguard Worker 	case DW_AT_defaulted:
7921*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_defaulted_name (num);
7922*7304104dSAndroid Build Coastguard Worker 	  break;
7923*7304104dSAndroid Build Coastguard Worker 	case DW_AT_visibility:
7924*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_visibility_name (num);
7925*7304104dSAndroid Build Coastguard Worker 	  break;
7926*7304104dSAndroid Build Coastguard Worker 	case DW_AT_virtuality:
7927*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_virtuality_name (num);
7928*7304104dSAndroid Build Coastguard Worker 	  break;
7929*7304104dSAndroid Build Coastguard Worker 	case DW_AT_identifier_case:
7930*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_identifier_case_name (num);
7931*7304104dSAndroid Build Coastguard Worker 	  break;
7932*7304104dSAndroid Build Coastguard Worker 	case DW_AT_calling_convention:
7933*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_calling_convention_name (num);
7934*7304104dSAndroid Build Coastguard Worker 	  break;
7935*7304104dSAndroid Build Coastguard Worker 	case DW_AT_inline:
7936*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_inline_name (num);
7937*7304104dSAndroid Build Coastguard Worker 	  break;
7938*7304104dSAndroid Build Coastguard Worker 	case DW_AT_ordering:
7939*7304104dSAndroid Build Coastguard Worker 	  valuestr = dwarf_ordering_name (num);
7940*7304104dSAndroid Build Coastguard Worker 	  break;
7941*7304104dSAndroid Build Coastguard Worker 	case DW_AT_decl_file:
7942*7304104dSAndroid Build Coastguard Worker 	case DW_AT_call_file:
7943*7304104dSAndroid Build Coastguard Worker 	  {
7944*7304104dSAndroid Build Coastguard Worker 	    if (cbargs->silent)
7945*7304104dSAndroid Build Coastguard Worker 	      break;
7946*7304104dSAndroid Build Coastguard Worker 
7947*7304104dSAndroid Build Coastguard Worker 	    /* Try to get the actual file, the current interface only
7948*7304104dSAndroid Build Coastguard Worker 	       gives us full paths, but we only want to show the file
7949*7304104dSAndroid Build Coastguard Worker 	       name for now.  */
7950*7304104dSAndroid Build Coastguard Worker 	    Dwarf_Die cudie;
7951*7304104dSAndroid Build Coastguard Worker 	    if (dwarf_cu_die (cbargs->cu, &cudie,
7952*7304104dSAndroid Build Coastguard Worker 			      NULL, NULL, NULL, NULL, NULL, NULL) != NULL)
7953*7304104dSAndroid Build Coastguard Worker 	      {
7954*7304104dSAndroid Build Coastguard Worker 		Dwarf_Files *files;
7955*7304104dSAndroid Build Coastguard Worker 		size_t nfiles;
7956*7304104dSAndroid Build Coastguard Worker 		if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
7957*7304104dSAndroid Build Coastguard Worker 		  {
7958*7304104dSAndroid Build Coastguard Worker 		    valuestr = dwarf_filesrc (files, num, NULL, NULL);
7959*7304104dSAndroid Build Coastguard Worker 		    if (valuestr != NULL)
7960*7304104dSAndroid Build Coastguard Worker 		      {
7961*7304104dSAndroid Build Coastguard Worker 			char *filename = strrchr (valuestr, '/');
7962*7304104dSAndroid Build Coastguard Worker 			if (filename != NULL)
7963*7304104dSAndroid Build Coastguard Worker 			  valuestr = filename + 1;
7964*7304104dSAndroid Build Coastguard Worker 		      }
7965*7304104dSAndroid Build Coastguard Worker 		    else
7966*7304104dSAndroid Build Coastguard Worker 		      error (0, 0, _("invalid file (%" PRId64 "): %s"),
7967*7304104dSAndroid Build Coastguard Worker 			     num, dwarf_errmsg (-1));
7968*7304104dSAndroid Build Coastguard Worker 		  }
7969*7304104dSAndroid Build Coastguard Worker 		else
7970*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("no srcfiles for CU [%" PRIx64 "]"),
7971*7304104dSAndroid Build Coastguard Worker 			 dwarf_dieoffset (&cudie));
7972*7304104dSAndroid Build Coastguard Worker 	      }
7973*7304104dSAndroid Build Coastguard Worker 	    else
7974*7304104dSAndroid Build Coastguard Worker 	     error (0, 0, _("couldn't get DWARF CU: %s"),
7975*7304104dSAndroid Build Coastguard Worker 		    dwarf_errmsg (-1));
7976*7304104dSAndroid Build Coastguard Worker 	    if (valuestr == NULL)
7977*7304104dSAndroid Build Coastguard Worker 	      valuestr = "???";
7978*7304104dSAndroid Build Coastguard Worker 	  }
7979*7304104dSAndroid Build Coastguard Worker 	  break;
7980*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_dwo_id:
7981*7304104dSAndroid Build Coastguard Worker 	  as_hex_id = true;
7982*7304104dSAndroid Build Coastguard Worker 	  break;
7983*7304104dSAndroid Build Coastguard Worker 
7984*7304104dSAndroid Build Coastguard Worker 	default:
7985*7304104dSAndroid Build Coastguard Worker 	  /* Nothing.  */
7986*7304104dSAndroid Build Coastguard Worker 	  break;
7987*7304104dSAndroid Build Coastguard Worker 	}
7988*7304104dSAndroid Build Coastguard Worker 
7989*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
7990*7304104dSAndroid Build Coastguard Worker 	break;
7991*7304104dSAndroid Build Coastguard Worker 
7992*7304104dSAndroid Build Coastguard Worker       /* When highpc is in constant form it is relative to lowpc.
7993*7304104dSAndroid Build Coastguard Worker 	 In that case also show the address.  */
7994*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr highpc;
7995*7304104dSAndroid Build Coastguard Worker       if (attr == DW_AT_high_pc && dwarf_highpc (die, &highpc) == 0)
7996*7304104dSAndroid Build Coastguard Worker 	{
7997*7304104dSAndroid Build Coastguard Worker 	  printf ("           %*s%-20s (%s) %" PRIuMAX " (",
7998*7304104dSAndroid Build Coastguard Worker 		  (int) (level * 2), "", dwarf_attr_name (attr),
7999*7304104dSAndroid Build Coastguard Worker 		  dwarf_form_name (form), (uintmax_t) num);
8000*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
8001*7304104dSAndroid Build Coastguard Worker 	  printf (")\n");
8002*7304104dSAndroid Build Coastguard Worker 	}
8003*7304104dSAndroid Build Coastguard Worker       else
8004*7304104dSAndroid Build Coastguard Worker 	{
8005*7304104dSAndroid Build Coastguard Worker 	  if (as_hex_id)
8006*7304104dSAndroid Build Coastguard Worker 	    {
8007*7304104dSAndroid Build Coastguard Worker 	      printf ("           %*s%-20s (%s) 0x%.16" PRIx64 "\n",
8008*7304104dSAndroid Build Coastguard Worker 		      (int) (level * 2), "", dwarf_attr_name (attr),
8009*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form), num);
8010*7304104dSAndroid Build Coastguard Worker 	    }
8011*7304104dSAndroid Build Coastguard Worker 	  else
8012*7304104dSAndroid Build Coastguard Worker 	    {
8013*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Sword snum = 0;
8014*7304104dSAndroid Build Coastguard Worker 	      bool is_signed;
8015*7304104dSAndroid Build Coastguard Worker 	      int bytes = 0;
8016*7304104dSAndroid Build Coastguard Worker 	      if (attr == DW_AT_const_value)
8017*7304104dSAndroid Build Coastguard Worker 		die_type_sign_bytes (die, &is_signed, &bytes);
8018*7304104dSAndroid Build Coastguard Worker 	      else
8019*7304104dSAndroid Build Coastguard Worker 		is_signed = (form == DW_FORM_sdata
8020*7304104dSAndroid Build Coastguard Worker 			     || form == DW_FORM_implicit_const);
8021*7304104dSAndroid Build Coastguard Worker 
8022*7304104dSAndroid Build Coastguard Worker 	      if (is_signed)
8023*7304104dSAndroid Build Coastguard Worker 		if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
8024*7304104dSAndroid Build Coastguard Worker 		  goto attrval_out;
8025*7304104dSAndroid Build Coastguard Worker 
8026*7304104dSAndroid Build Coastguard Worker 	      if (valuestr == NULL)
8027*7304104dSAndroid Build Coastguard Worker 		{
8028*7304104dSAndroid Build Coastguard Worker 		  printf ("           %*s%-20s (%s) ",
8029*7304104dSAndroid Build Coastguard Worker 			  (int) (level * 2), "", dwarf_attr_name (attr),
8030*7304104dSAndroid Build Coastguard Worker 			  dwarf_form_name (form));
8031*7304104dSAndroid Build Coastguard Worker 		}
8032*7304104dSAndroid Build Coastguard Worker 	      else
8033*7304104dSAndroid Build Coastguard Worker 		{
8034*7304104dSAndroid Build Coastguard Worker 		  printf ("           %*s%-20s (%s) %s (",
8035*7304104dSAndroid Build Coastguard Worker 			  (int) (level * 2), "", dwarf_attr_name (attr),
8036*7304104dSAndroid Build Coastguard Worker 			  dwarf_form_name (form), valuestr);
8037*7304104dSAndroid Build Coastguard Worker 		}
8038*7304104dSAndroid Build Coastguard Worker 
8039*7304104dSAndroid Build Coastguard Worker 	      switch (bytes)
8040*7304104dSAndroid Build Coastguard Worker 		{
8041*7304104dSAndroid Build Coastguard Worker 		case 1:
8042*7304104dSAndroid Build Coastguard Worker 		  if (is_signed)
8043*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRId8, (int8_t) snum);
8044*7304104dSAndroid Build Coastguard Worker 		  else
8045*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRIu8, (uint8_t) num);
8046*7304104dSAndroid Build Coastguard Worker 		  break;
8047*7304104dSAndroid Build Coastguard Worker 
8048*7304104dSAndroid Build Coastguard Worker 		case 2:
8049*7304104dSAndroid Build Coastguard Worker 		  if (is_signed)
8050*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRId16, (int16_t) snum);
8051*7304104dSAndroid Build Coastguard Worker 		  else
8052*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRIu16, (uint16_t) num);
8053*7304104dSAndroid Build Coastguard Worker 		  break;
8054*7304104dSAndroid Build Coastguard Worker 
8055*7304104dSAndroid Build Coastguard Worker 		case 4:
8056*7304104dSAndroid Build Coastguard Worker 		  if (is_signed)
8057*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRId32, (int32_t) snum);
8058*7304104dSAndroid Build Coastguard Worker 		  else
8059*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRIu32, (uint32_t) num);
8060*7304104dSAndroid Build Coastguard Worker 		  break;
8061*7304104dSAndroid Build Coastguard Worker 
8062*7304104dSAndroid Build Coastguard Worker 		case 8:
8063*7304104dSAndroid Build Coastguard Worker 		  if (is_signed)
8064*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRId64, (int64_t) snum);
8065*7304104dSAndroid Build Coastguard Worker 		  else
8066*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRIu64, (uint64_t) num);
8067*7304104dSAndroid Build Coastguard Worker 		  break;
8068*7304104dSAndroid Build Coastguard Worker 
8069*7304104dSAndroid Build Coastguard Worker 		default:
8070*7304104dSAndroid Build Coastguard Worker 		  if (is_signed)
8071*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRIdMAX, (intmax_t) snum);
8072*7304104dSAndroid Build Coastguard Worker 		  else
8073*7304104dSAndroid Build Coastguard Worker 		    printf ("%" PRIuMAX, (uintmax_t) num);
8074*7304104dSAndroid Build Coastguard Worker 		  break;
8075*7304104dSAndroid Build Coastguard Worker 		}
8076*7304104dSAndroid Build Coastguard Worker 
8077*7304104dSAndroid Build Coastguard Worker 	      /* Make clear if we switched from a signed encoding to
8078*7304104dSAndroid Build Coastguard Worker 		 an unsigned value.  */
8079*7304104dSAndroid Build Coastguard Worker 	      if (attr == DW_AT_const_value
8080*7304104dSAndroid Build Coastguard Worker 		  && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
8081*7304104dSAndroid Build Coastguard Worker 		  && !is_signed)
8082*7304104dSAndroid Build Coastguard Worker 		printf (" (%" PRIdMAX ")", (intmax_t) num);
8083*7304104dSAndroid Build Coastguard Worker 
8084*7304104dSAndroid Build Coastguard Worker 	      if (valuestr == NULL)
8085*7304104dSAndroid Build Coastguard Worker 		printf ("\n");
8086*7304104dSAndroid Build Coastguard Worker 	      else
8087*7304104dSAndroid Build Coastguard Worker 		printf (")\n");
8088*7304104dSAndroid Build Coastguard Worker 	    }
8089*7304104dSAndroid Build Coastguard Worker 	}
8090*7304104dSAndroid Build Coastguard Worker       break;
8091*7304104dSAndroid Build Coastguard Worker 
8092*7304104dSAndroid Build Coastguard Worker     case DW_FORM_flag:
8093*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
8094*7304104dSAndroid Build Coastguard Worker 	break;
8095*7304104dSAndroid Build Coastguard Worker       bool flag;
8096*7304104dSAndroid Build Coastguard Worker       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
8097*7304104dSAndroid Build Coastguard Worker 	goto attrval_out;
8098*7304104dSAndroid Build Coastguard Worker 
8099*7304104dSAndroid Build Coastguard Worker       printf ("           %*s%-20s (%s) %s\n",
8100*7304104dSAndroid Build Coastguard Worker 	      (int) (level * 2), "", dwarf_attr_name (attr),
8101*7304104dSAndroid Build Coastguard Worker 	      dwarf_form_name (form), flag ? yes_str : no_str);
8102*7304104dSAndroid Build Coastguard Worker       break;
8103*7304104dSAndroid Build Coastguard Worker 
8104*7304104dSAndroid Build Coastguard Worker     case DW_FORM_flag_present:
8105*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
8106*7304104dSAndroid Build Coastguard Worker 	break;
8107*7304104dSAndroid Build Coastguard Worker       printf ("           %*s%-20s (%s) %s\n",
8108*7304104dSAndroid Build Coastguard Worker 	      (int) (level * 2), "", dwarf_attr_name (attr),
8109*7304104dSAndroid Build Coastguard Worker 	      dwarf_form_name (form), yes_str);
8110*7304104dSAndroid Build Coastguard Worker       break;
8111*7304104dSAndroid Build Coastguard Worker 
8112*7304104dSAndroid Build Coastguard Worker     case DW_FORM_exprloc:
8113*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block4:
8114*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block2:
8115*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block1:
8116*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block:
8117*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data16: /* DWARF5 calls this a constant class.  */
8118*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
8119*7304104dSAndroid Build Coastguard Worker 	break;
8120*7304104dSAndroid Build Coastguard Worker       Dwarf_Block block;
8121*7304104dSAndroid Build Coastguard Worker       if (unlikely (dwarf_formblock (attrp, &block) != 0))
8122*7304104dSAndroid Build Coastguard Worker 	goto attrval_out;
8123*7304104dSAndroid Build Coastguard Worker 
8124*7304104dSAndroid Build Coastguard Worker       printf ("           %*s%-20s (%s) ",
8125*7304104dSAndroid Build Coastguard Worker 	      (int) (level * 2), "", dwarf_attr_name (attr),
8126*7304104dSAndroid Build Coastguard Worker 	      dwarf_form_name (form));
8127*7304104dSAndroid Build Coastguard Worker 
8128*7304104dSAndroid Build Coastguard Worker       switch (attr)
8129*7304104dSAndroid Build Coastguard Worker 	{
8130*7304104dSAndroid Build Coastguard Worker 	default:
8131*7304104dSAndroid Build Coastguard Worker 	  if (form != DW_FORM_exprloc)
8132*7304104dSAndroid Build Coastguard Worker 	    {
8133*7304104dSAndroid Build Coastguard Worker 	      print_block (block.length, block.data);
8134*7304104dSAndroid Build Coastguard Worker 	      break;
8135*7304104dSAndroid Build Coastguard Worker 	    }
8136*7304104dSAndroid Build Coastguard Worker 	  FALLTHROUGH;
8137*7304104dSAndroid Build Coastguard Worker 
8138*7304104dSAndroid Build Coastguard Worker 	case DW_AT_location:
8139*7304104dSAndroid Build Coastguard Worker 	case DW_AT_data_location:
8140*7304104dSAndroid Build Coastguard Worker 	case DW_AT_data_member_location:
8141*7304104dSAndroid Build Coastguard Worker 	case DW_AT_vtable_elem_location:
8142*7304104dSAndroid Build Coastguard Worker 	case DW_AT_string_length:
8143*7304104dSAndroid Build Coastguard Worker 	case DW_AT_use_location:
8144*7304104dSAndroid Build Coastguard Worker 	case DW_AT_frame_base:
8145*7304104dSAndroid Build Coastguard Worker 	case DW_AT_return_addr:
8146*7304104dSAndroid Build Coastguard Worker 	case DW_AT_static_link:
8147*7304104dSAndroid Build Coastguard Worker 	case DW_AT_allocated:
8148*7304104dSAndroid Build Coastguard Worker 	case DW_AT_associated:
8149*7304104dSAndroid Build Coastguard Worker 	case DW_AT_bit_size:
8150*7304104dSAndroid Build Coastguard Worker 	case DW_AT_bit_offset:
8151*7304104dSAndroid Build Coastguard Worker 	case DW_AT_bit_stride:
8152*7304104dSAndroid Build Coastguard Worker 	case DW_AT_byte_size:
8153*7304104dSAndroid Build Coastguard Worker 	case DW_AT_byte_stride:
8154*7304104dSAndroid Build Coastguard Worker 	case DW_AT_count:
8155*7304104dSAndroid Build Coastguard Worker 	case DW_AT_lower_bound:
8156*7304104dSAndroid Build Coastguard Worker 	case DW_AT_upper_bound:
8157*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_value:
8158*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_data_value:
8159*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_target:
8160*7304104dSAndroid Build Coastguard Worker 	case DW_AT_GNU_call_site_target_clobbered:
8161*7304104dSAndroid Build Coastguard Worker 	  if (form == DW_FORM_exprloc
8162*7304104dSAndroid Build Coastguard Worker 	      || (form != DW_FORM_data16
8163*7304104dSAndroid Build Coastguard Worker 		  && attrp->cu->version < 4)) /* blocks were expressions.  */
8164*7304104dSAndroid Build Coastguard Worker 	    {
8165*7304104dSAndroid Build Coastguard Worker 	      putchar ('\n');
8166*7304104dSAndroid Build Coastguard Worker 	      print_ops (cbargs->dwflmod, cbargs->dbg,
8167*7304104dSAndroid Build Coastguard Worker 			 12 + level * 2, 12 + level * 2,
8168*7304104dSAndroid Build Coastguard Worker 			 cbargs->version, cbargs->addrsize, cbargs->offset_size,
8169*7304104dSAndroid Build Coastguard Worker 			 attrp->cu, block.length, block.data);
8170*7304104dSAndroid Build Coastguard Worker 	    }
8171*7304104dSAndroid Build Coastguard Worker 	  else
8172*7304104dSAndroid Build Coastguard Worker 	    print_block (block.length, block.data);
8173*7304104dSAndroid Build Coastguard Worker 	  break;
8174*7304104dSAndroid Build Coastguard Worker 
8175*7304104dSAndroid Build Coastguard Worker 	case DW_AT_discr_list:
8176*7304104dSAndroid Build Coastguard Worker 	  if (block.length == 0)
8177*7304104dSAndroid Build Coastguard Worker 	    puts ("<default>");
8178*7304104dSAndroid Build Coastguard Worker 	  else if (form != DW_FORM_data16)
8179*7304104dSAndroid Build Coastguard Worker 	    {
8180*7304104dSAndroid Build Coastguard Worker 	      const unsigned char *readp = block.data;
8181*7304104dSAndroid Build Coastguard Worker 	      const unsigned char *readendp = readp + block.length;
8182*7304104dSAndroid Build Coastguard Worker 
8183*7304104dSAndroid Build Coastguard Worker 	      /* See if we are dealing with a signed or unsigned
8184*7304104dSAndroid Build Coastguard Worker 		 values.  If the parent of this variant DIE is a
8185*7304104dSAndroid Build Coastguard Worker 		 variant_part then it will either have a discriminant
8186*7304104dSAndroid Build Coastguard Worker 		 which points to the member which type is the
8187*7304104dSAndroid Build Coastguard Worker 		 discriminant type.  Or the variant_part itself has a
8188*7304104dSAndroid Build Coastguard Worker 		 type representing the discriminant.  */
8189*7304104dSAndroid Build Coastguard Worker 	      bool is_signed = false;
8190*7304104dSAndroid Build Coastguard Worker 	      if (level > 0)
8191*7304104dSAndroid Build Coastguard Worker 		{
8192*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Die *parent = &cbargs->dies[level - 1];
8193*7304104dSAndroid Build Coastguard Worker 		  if (dwarf_tag (die) == DW_TAG_variant
8194*7304104dSAndroid Build Coastguard Worker 		      && dwarf_tag (parent) == DW_TAG_variant_part)
8195*7304104dSAndroid Build Coastguard Worker 		    {
8196*7304104dSAndroid Build Coastguard Worker 		      Dwarf_Die member;
8197*7304104dSAndroid Build Coastguard Worker 		      Dwarf_Attribute discr_attr;
8198*7304104dSAndroid Build Coastguard Worker 		      int bytes;
8199*7304104dSAndroid Build Coastguard Worker 		      if (dwarf_formref_die (dwarf_attr (parent,
8200*7304104dSAndroid Build Coastguard Worker 							 DW_AT_discr,
8201*7304104dSAndroid Build Coastguard Worker 							 &discr_attr),
8202*7304104dSAndroid Build Coastguard Worker 					     &member) != NULL)
8203*7304104dSAndroid Build Coastguard Worker 			die_type_sign_bytes (&member, &is_signed, &bytes);
8204*7304104dSAndroid Build Coastguard Worker 		      else
8205*7304104dSAndroid Build Coastguard Worker 			die_type_sign_bytes (parent, &is_signed, &bytes);
8206*7304104dSAndroid Build Coastguard Worker 		    }
8207*7304104dSAndroid Build Coastguard Worker 		}
8208*7304104dSAndroid Build Coastguard Worker 	      while (readp < readendp)
8209*7304104dSAndroid Build Coastguard Worker 		{
8210*7304104dSAndroid Build Coastguard Worker 		  int d = (int) *readp++;
8211*7304104dSAndroid Build Coastguard Worker 		  printf ("%s ", dwarf_discr_list_name (d));
8212*7304104dSAndroid Build Coastguard Worker 		  if (readp >= readendp)
8213*7304104dSAndroid Build Coastguard Worker 		    goto attrval_out;
8214*7304104dSAndroid Build Coastguard Worker 
8215*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Word val;
8216*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Sword sval;
8217*7304104dSAndroid Build Coastguard Worker 		  if (d == DW_DSC_label)
8218*7304104dSAndroid Build Coastguard Worker 		    {
8219*7304104dSAndroid Build Coastguard Worker 		      if (is_signed)
8220*7304104dSAndroid Build Coastguard Worker 			{
8221*7304104dSAndroid Build Coastguard Worker 			  get_sleb128 (sval, readp, readendp);
8222*7304104dSAndroid Build Coastguard Worker 			  printf ("%" PRId64 "", sval);
8223*7304104dSAndroid Build Coastguard Worker 			}
8224*7304104dSAndroid Build Coastguard Worker 		      else
8225*7304104dSAndroid Build Coastguard Worker 			{
8226*7304104dSAndroid Build Coastguard Worker 			  get_uleb128 (val, readp, readendp);
8227*7304104dSAndroid Build Coastguard Worker 			  printf ("%" PRIu64 "", val);
8228*7304104dSAndroid Build Coastguard Worker 			}
8229*7304104dSAndroid Build Coastguard Worker 		    }
8230*7304104dSAndroid Build Coastguard Worker 		  else if (d == DW_DSC_range)
8231*7304104dSAndroid Build Coastguard Worker 		    {
8232*7304104dSAndroid Build Coastguard Worker 		      if (is_signed)
8233*7304104dSAndroid Build Coastguard Worker 			{
8234*7304104dSAndroid Build Coastguard Worker 			  get_sleb128 (sval, readp, readendp);
8235*7304104dSAndroid Build Coastguard Worker 			  printf ("%" PRId64 "..", sval);
8236*7304104dSAndroid Build Coastguard Worker 			  if (readp >= readendp)
8237*7304104dSAndroid Build Coastguard Worker 			    goto attrval_out;
8238*7304104dSAndroid Build Coastguard Worker 			  get_sleb128 (sval, readp, readendp);
8239*7304104dSAndroid Build Coastguard Worker 			  printf ("%" PRId64 "", sval);
8240*7304104dSAndroid Build Coastguard Worker 			}
8241*7304104dSAndroid Build Coastguard Worker 		      else
8242*7304104dSAndroid Build Coastguard Worker 			{
8243*7304104dSAndroid Build Coastguard Worker 			  get_uleb128 (val, readp, readendp);
8244*7304104dSAndroid Build Coastguard Worker 			  printf ("%" PRIu64 "..", val);
8245*7304104dSAndroid Build Coastguard Worker 			  if (readp >= readendp)
8246*7304104dSAndroid Build Coastguard Worker 			    goto attrval_out;
8247*7304104dSAndroid Build Coastguard Worker 			  get_uleb128 (val, readp, readendp);
8248*7304104dSAndroid Build Coastguard Worker 			  printf ("%" PRIu64 "", val);
8249*7304104dSAndroid Build Coastguard Worker 			}
8250*7304104dSAndroid Build Coastguard Worker 		    }
8251*7304104dSAndroid Build Coastguard Worker 		  else
8252*7304104dSAndroid Build Coastguard Worker 		    {
8253*7304104dSAndroid Build Coastguard Worker 		      print_block (readendp - readp, readp);
8254*7304104dSAndroid Build Coastguard Worker 		      break;
8255*7304104dSAndroid Build Coastguard Worker 		    }
8256*7304104dSAndroid Build Coastguard Worker 		  if (readp < readendp)
8257*7304104dSAndroid Build Coastguard Worker 		    printf (", ");
8258*7304104dSAndroid Build Coastguard Worker 		}
8259*7304104dSAndroid Build Coastguard Worker 	      putchar ('\n');
8260*7304104dSAndroid Build Coastguard Worker 	    }
8261*7304104dSAndroid Build Coastguard Worker 	  else
8262*7304104dSAndroid Build Coastguard Worker 	    print_block (block.length, block.data);
8263*7304104dSAndroid Build Coastguard Worker 	  break;
8264*7304104dSAndroid Build Coastguard Worker 	}
8265*7304104dSAndroid Build Coastguard Worker       break;
8266*7304104dSAndroid Build Coastguard Worker 
8267*7304104dSAndroid Build Coastguard Worker     default:
8268*7304104dSAndroid Build Coastguard Worker       if (cbargs->silent)
8269*7304104dSAndroid Build Coastguard Worker 	break;
8270*7304104dSAndroid Build Coastguard Worker       printf ("           %*s%-20s (%s) ???\n",
8271*7304104dSAndroid Build Coastguard Worker 	      (int) (level * 2), "", dwarf_attr_name (attr),
8272*7304104dSAndroid Build Coastguard Worker 	      dwarf_form_name (form));
8273*7304104dSAndroid Build Coastguard Worker       break;
8274*7304104dSAndroid Build Coastguard Worker     }
8275*7304104dSAndroid Build Coastguard Worker 
8276*7304104dSAndroid Build Coastguard Worker   return DWARF_CB_OK;
8277*7304104dSAndroid Build Coastguard Worker }
8278*7304104dSAndroid Build Coastguard Worker 
8279*7304104dSAndroid Build Coastguard Worker static void
print_debug_units(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg,bool debug_types)8280*7304104dSAndroid Build Coastguard Worker print_debug_units (Dwfl_Module *dwflmod,
8281*7304104dSAndroid Build Coastguard Worker 		   Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
8282*7304104dSAndroid Build Coastguard Worker 		   Elf_Scn *scn, GElf_Shdr *shdr,
8283*7304104dSAndroid Build Coastguard Worker 		   Dwarf *dbg, bool debug_types)
8284*7304104dSAndroid Build Coastguard Worker {
8285*7304104dSAndroid Build Coastguard Worker   const bool silent = !(print_debug_sections & section_info) && !debug_types;
8286*7304104dSAndroid Build Coastguard Worker   const char *secname = section_name (ebl, shdr);
8287*7304104dSAndroid Build Coastguard Worker 
8288*7304104dSAndroid Build Coastguard Worker   /* Check section actually exists.  */
8289*7304104dSAndroid Build Coastguard Worker   if (!silent)
8290*7304104dSAndroid Build Coastguard Worker     if (get_debug_elf_data (dbg, ebl,
8291*7304104dSAndroid Build Coastguard Worker 			    debug_types ? IDX_debug_types : IDX_debug_info,
8292*7304104dSAndroid Build Coastguard Worker 			    scn) == NULL)
8293*7304104dSAndroid Build Coastguard Worker       return;
8294*7304104dSAndroid Build Coastguard Worker 
8295*7304104dSAndroid Build Coastguard Worker   if (!silent)
8296*7304104dSAndroid Build Coastguard Worker     printf (_("\
8297*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
8298*7304104dSAndroid Build Coastguard Worker 	    elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
8299*7304104dSAndroid Build Coastguard Worker 
8300*7304104dSAndroid Build Coastguard Worker   /* If the section is empty we don't have to do anything.  */
8301*7304104dSAndroid Build Coastguard Worker   if (!silent && shdr->sh_size == 0)
8302*7304104dSAndroid Build Coastguard Worker     return;
8303*7304104dSAndroid Build Coastguard Worker 
8304*7304104dSAndroid Build Coastguard Worker   int maxdies = 20;
8305*7304104dSAndroid Build Coastguard Worker   Dwarf_Die *dies = xmalloc (maxdies * sizeof (Dwarf_Die));
8306*7304104dSAndroid Build Coastguard Worker 
8307*7304104dSAndroid Build Coastguard Worker   /* New compilation unit.  */
8308*7304104dSAndroid Build Coastguard Worker   Dwarf_Half version;
8309*7304104dSAndroid Build Coastguard Worker 
8310*7304104dSAndroid Build Coastguard Worker   Dwarf_Die result;
8311*7304104dSAndroid Build Coastguard Worker   Dwarf_Off abbroffset;
8312*7304104dSAndroid Build Coastguard Worker   uint8_t addrsize;
8313*7304104dSAndroid Build Coastguard Worker   uint8_t offsize;
8314*7304104dSAndroid Build Coastguard Worker   uint64_t unit_id;
8315*7304104dSAndroid Build Coastguard Worker   Dwarf_Off subdie_off;
8316*7304104dSAndroid Build Coastguard Worker 
8317*7304104dSAndroid Build Coastguard Worker   int unit_res;
8318*7304104dSAndroid Build Coastguard Worker   Dwarf_CU *cu;
8319*7304104dSAndroid Build Coastguard Worker   Dwarf_CU cu_mem;
8320*7304104dSAndroid Build Coastguard Worker   uint8_t unit_type;
8321*7304104dSAndroid Build Coastguard Worker   Dwarf_Die cudie;
8322*7304104dSAndroid Build Coastguard Worker 
8323*7304104dSAndroid Build Coastguard Worker   /* We cheat a little because we want to see only the CUs from .debug_info
8324*7304104dSAndroid Build Coastguard Worker      or .debug_types.  We know the Dwarf_CU struct layout.  Set it up at
8325*7304104dSAndroid Build Coastguard Worker      the end of .debug_info if we want .debug_types only.  Check the returned
8326*7304104dSAndroid Build Coastguard Worker      Dwarf_CU is still in the expected section.  */
8327*7304104dSAndroid Build Coastguard Worker   if (debug_types)
8328*7304104dSAndroid Build Coastguard Worker     {
8329*7304104dSAndroid Build Coastguard Worker       cu_mem.dbg = dbg;
8330*7304104dSAndroid Build Coastguard Worker       cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size;
8331*7304104dSAndroid Build Coastguard Worker       cu_mem.sec_idx = IDX_debug_info;
8332*7304104dSAndroid Build Coastguard Worker       cu = &cu_mem;
8333*7304104dSAndroid Build Coastguard Worker     }
8334*7304104dSAndroid Build Coastguard Worker   else
8335*7304104dSAndroid Build Coastguard Worker     cu = NULL;
8336*7304104dSAndroid Build Coastguard Worker 
8337*7304104dSAndroid Build Coastguard Worker  next_cu:
8338*7304104dSAndroid Build Coastguard Worker   unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
8339*7304104dSAndroid Build Coastguard Worker 			      &cudie, NULL);
8340*7304104dSAndroid Build Coastguard Worker   if (unit_res == 1)
8341*7304104dSAndroid Build Coastguard Worker     goto do_return;
8342*7304104dSAndroid Build Coastguard Worker 
8343*7304104dSAndroid Build Coastguard Worker   if (unit_res == -1)
8344*7304104dSAndroid Build Coastguard Worker     {
8345*7304104dSAndroid Build Coastguard Worker       if (!silent)
8346*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("cannot get next unit: %s"), dwarf_errmsg (-1));
8347*7304104dSAndroid Build Coastguard Worker       goto do_return;
8348*7304104dSAndroid Build Coastguard Worker     }
8349*7304104dSAndroid Build Coastguard Worker 
8350*7304104dSAndroid Build Coastguard Worker   if (cu->sec_idx != (size_t) (debug_types ? IDX_debug_types : IDX_debug_info))
8351*7304104dSAndroid Build Coastguard Worker     goto do_return;
8352*7304104dSAndroid Build Coastguard Worker 
8353*7304104dSAndroid Build Coastguard Worker   dwarf_cu_die (cu, &result, NULL, &abbroffset, &addrsize, &offsize,
8354*7304104dSAndroid Build Coastguard Worker 		&unit_id, &subdie_off);
8355*7304104dSAndroid Build Coastguard Worker 
8356*7304104dSAndroid Build Coastguard Worker   if (!silent)
8357*7304104dSAndroid Build Coastguard Worker     {
8358*7304104dSAndroid Build Coastguard Worker       Dwarf_Off offset = cu->start;
8359*7304104dSAndroid Build Coastguard Worker       if (debug_types && version < 5)
8360*7304104dSAndroid Build Coastguard Worker 	{
8361*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Die typedie;
8362*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off dieoffset;
8363*7304104dSAndroid Build Coastguard Worker 	  dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, cu->start
8364*7304104dSAndroid Build Coastguard Worker 							   + subdie_off,
8365*7304104dSAndroid Build Coastguard Worker 							   &typedie));
8366*7304104dSAndroid Build Coastguard Worker 	  printf (_(" Type unit at offset %" PRIu64 ":\n"
8367*7304104dSAndroid Build Coastguard Worker 			   " Version: %" PRIu16
8368*7304104dSAndroid Build Coastguard Worker 			   ", Abbreviation section offset: %" PRIu64
8369*7304104dSAndroid Build Coastguard Worker 			   ", Address size: %" PRIu8
8370*7304104dSAndroid Build Coastguard Worker 			   ", Offset size: %" PRIu8
8371*7304104dSAndroid Build Coastguard Worker 			   "\n Type signature: %#" PRIx64
8372*7304104dSAndroid Build Coastguard Worker 			   ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
8373*7304104dSAndroid Build Coastguard Worker 		  (uint64_t) offset, version, abbroffset, addrsize, offsize,
8374*7304104dSAndroid Build Coastguard Worker 		  unit_id, (uint64_t) subdie_off, dieoffset);
8375*7304104dSAndroid Build Coastguard Worker 	}
8376*7304104dSAndroid Build Coastguard Worker       else
8377*7304104dSAndroid Build Coastguard Worker 	{
8378*7304104dSAndroid Build Coastguard Worker 	  printf (_(" Compilation unit at offset %" PRIu64 ":\n"
8379*7304104dSAndroid Build Coastguard Worker 			   " Version: %" PRIu16
8380*7304104dSAndroid Build Coastguard Worker 			   ", Abbreviation section offset: %" PRIu64
8381*7304104dSAndroid Build Coastguard Worker 			   ", Address size: %" PRIu8
8382*7304104dSAndroid Build Coastguard Worker 			   ", Offset size: %" PRIu8 "\n"),
8383*7304104dSAndroid Build Coastguard Worker 		  (uint64_t) offset, version, abbroffset, addrsize, offsize);
8384*7304104dSAndroid Build Coastguard Worker 
8385*7304104dSAndroid Build Coastguard Worker 	  if (version >= 5 || (unit_type != DW_UT_compile
8386*7304104dSAndroid Build Coastguard Worker 			       && unit_type != DW_UT_partial))
8387*7304104dSAndroid Build Coastguard Worker 	    {
8388*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Unit type: %s (%" PRIu8 ")"),
8389*7304104dSAndroid Build Coastguard Worker 			       dwarf_unit_name (unit_type), unit_type);
8390*7304104dSAndroid Build Coastguard Worker 	      if (unit_type == DW_UT_type
8391*7304104dSAndroid Build Coastguard Worker 		  || unit_type == DW_UT_skeleton
8392*7304104dSAndroid Build Coastguard Worker 		  || unit_type == DW_UT_split_compile
8393*7304104dSAndroid Build Coastguard Worker 		  || unit_type == DW_UT_split_type)
8394*7304104dSAndroid Build Coastguard Worker 		printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
8395*7304104dSAndroid Build Coastguard Worker 	      if (unit_type == DW_UT_type
8396*7304104dSAndroid Build Coastguard Worker 		  || unit_type == DW_UT_split_type)
8397*7304104dSAndroid Build Coastguard Worker 		{
8398*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Die typedie;
8399*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Off dieoffset;
8400*7304104dSAndroid Build Coastguard Worker 		  dwarf_cu_info (cu, NULL, NULL, NULL, &typedie,
8401*7304104dSAndroid Build Coastguard Worker 				 NULL, NULL, NULL);
8402*7304104dSAndroid Build Coastguard Worker 		  dieoffset = dwarf_dieoffset (&typedie);
8403*7304104dSAndroid Build Coastguard Worker 		  printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
8404*7304104dSAndroid Build Coastguard Worker 			  subdie_off, dieoffset);
8405*7304104dSAndroid Build Coastguard Worker 		}
8406*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
8407*7304104dSAndroid Build Coastguard Worker 	    }
8408*7304104dSAndroid Build Coastguard Worker 	}
8409*7304104dSAndroid Build Coastguard Worker     }
8410*7304104dSAndroid Build Coastguard Worker 
8411*7304104dSAndroid Build Coastguard Worker   if (version < 2 || version > 5
8412*7304104dSAndroid Build Coastguard Worker       || unit_type < DW_UT_compile || unit_type > DW_UT_split_type)
8413*7304104dSAndroid Build Coastguard Worker     {
8414*7304104dSAndroid Build Coastguard Worker       if (!silent)
8415*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("unknown version (%d) or unit type (%d)"),
8416*7304104dSAndroid Build Coastguard Worker 	       version, unit_type);
8417*7304104dSAndroid Build Coastguard Worker       goto next_cu;
8418*7304104dSAndroid Build Coastguard Worker     }
8419*7304104dSAndroid Build Coastguard Worker 
8420*7304104dSAndroid Build Coastguard Worker   struct attrcb_args args =
8421*7304104dSAndroid Build Coastguard Worker     {
8422*7304104dSAndroid Build Coastguard Worker       .dwflmod = dwflmod,
8423*7304104dSAndroid Build Coastguard Worker       .silent = silent,
8424*7304104dSAndroid Build Coastguard Worker       .version = version,
8425*7304104dSAndroid Build Coastguard Worker       .addrsize = addrsize,
8426*7304104dSAndroid Build Coastguard Worker       .offset_size = offsize
8427*7304104dSAndroid Build Coastguard Worker     };
8428*7304104dSAndroid Build Coastguard Worker 
8429*7304104dSAndroid Build Coastguard Worker   bool is_split = false;
8430*7304104dSAndroid Build Coastguard Worker   int level = 0;
8431*7304104dSAndroid Build Coastguard Worker   dies[0] = cudie;
8432*7304104dSAndroid Build Coastguard Worker   args.cu = dies[0].cu;
8433*7304104dSAndroid Build Coastguard Worker   args.dbg = dbg;
8434*7304104dSAndroid Build Coastguard Worker   args.is_split = is_split;
8435*7304104dSAndroid Build Coastguard Worker 
8436*7304104dSAndroid Build Coastguard Worker   /* We might return here again for the split CU subdie.  */
8437*7304104dSAndroid Build Coastguard Worker   do_cu:
8438*7304104dSAndroid Build Coastguard Worker   do
8439*7304104dSAndroid Build Coastguard Worker     {
8440*7304104dSAndroid Build Coastguard Worker       Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
8441*7304104dSAndroid Build Coastguard Worker       if (unlikely (offset == (Dwarf_Off) -1))
8442*7304104dSAndroid Build Coastguard Worker 	{
8443*7304104dSAndroid Build Coastguard Worker 	  if (!silent)
8444*7304104dSAndroid Build Coastguard Worker 	    error (0, 0, _("cannot get DIE offset: %s"),
8445*7304104dSAndroid Build Coastguard Worker 		   dwarf_errmsg (-1));
8446*7304104dSAndroid Build Coastguard Worker 	  goto do_return;
8447*7304104dSAndroid Build Coastguard Worker 	}
8448*7304104dSAndroid Build Coastguard Worker 
8449*7304104dSAndroid Build Coastguard Worker       int tag = dwarf_tag (&dies[level]);
8450*7304104dSAndroid Build Coastguard Worker       if (unlikely (tag == DW_TAG_invalid))
8451*7304104dSAndroid Build Coastguard Worker 	{
8452*7304104dSAndroid Build Coastguard Worker 	  if (!silent)
8453*7304104dSAndroid Build Coastguard Worker 	    error (0, 0, _("cannot get tag of DIE at offset [%" PRIx64
8454*7304104dSAndroid Build Coastguard Worker 				  "] in section '%s': %s"),
8455*7304104dSAndroid Build Coastguard Worker 		   (uint64_t) offset, secname, dwarf_errmsg (-1));
8456*7304104dSAndroid Build Coastguard Worker 	  goto do_return;
8457*7304104dSAndroid Build Coastguard Worker 	}
8458*7304104dSAndroid Build Coastguard Worker 
8459*7304104dSAndroid Build Coastguard Worker       if (!silent)
8460*7304104dSAndroid Build Coastguard Worker 	{
8461*7304104dSAndroid Build Coastguard Worker 	  unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
8462*7304104dSAndroid Build Coastguard Worker 	  if (is_split)
8463*7304104dSAndroid Build Coastguard Worker 	    printf (" {%6" PRIx64 "}  ", (uint64_t) offset);
8464*7304104dSAndroid Build Coastguard Worker 	  else
8465*7304104dSAndroid Build Coastguard Worker 	    printf (" [%6" PRIx64 "]  ", (uint64_t) offset);
8466*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
8467*7304104dSAndroid Build Coastguard Worker 		  dwarf_tag_name (tag), code);
8468*7304104dSAndroid Build Coastguard Worker 	}
8469*7304104dSAndroid Build Coastguard Worker 
8470*7304104dSAndroid Build Coastguard Worker       /* Print the attribute values.  */
8471*7304104dSAndroid Build Coastguard Worker       args.level = level;
8472*7304104dSAndroid Build Coastguard Worker       args.dies = dies;
8473*7304104dSAndroid Build Coastguard Worker       (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
8474*7304104dSAndroid Build Coastguard Worker 
8475*7304104dSAndroid Build Coastguard Worker       /* Make room for the next level's DIE.  */
8476*7304104dSAndroid Build Coastguard Worker       if (level + 1 == maxdies)
8477*7304104dSAndroid Build Coastguard Worker 	dies = xrealloc (dies, (maxdies += 10) * sizeof (Dwarf_Die));
8478*7304104dSAndroid Build Coastguard Worker 
8479*7304104dSAndroid Build Coastguard Worker       int res = dwarf_child (&dies[level], &dies[level + 1]);
8480*7304104dSAndroid Build Coastguard Worker       if (res > 0)
8481*7304104dSAndroid Build Coastguard Worker 	{
8482*7304104dSAndroid Build Coastguard Worker 	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
8483*7304104dSAndroid Build Coastguard Worker 	    if (level-- == 0)
8484*7304104dSAndroid Build Coastguard Worker 	      break;
8485*7304104dSAndroid Build Coastguard Worker 
8486*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (res == -1))
8487*7304104dSAndroid Build Coastguard Worker 	    {
8488*7304104dSAndroid Build Coastguard Worker 	      if (!silent)
8489*7304104dSAndroid Build Coastguard Worker 		error (0, 0, _("cannot get next DIE: %s\n"),
8490*7304104dSAndroid Build Coastguard Worker 		       dwarf_errmsg (-1));
8491*7304104dSAndroid Build Coastguard Worker 	      goto do_return;
8492*7304104dSAndroid Build Coastguard Worker 	    }
8493*7304104dSAndroid Build Coastguard Worker 	}
8494*7304104dSAndroid Build Coastguard Worker       else if (unlikely (res < 0))
8495*7304104dSAndroid Build Coastguard Worker 	{
8496*7304104dSAndroid Build Coastguard Worker 	  if (!silent)
8497*7304104dSAndroid Build Coastguard Worker 	    error (0, 0, _("cannot get next DIE: %s"),
8498*7304104dSAndroid Build Coastguard Worker 		   dwarf_errmsg (-1));
8499*7304104dSAndroid Build Coastguard Worker 	  goto do_return;
8500*7304104dSAndroid Build Coastguard Worker 	}
8501*7304104dSAndroid Build Coastguard Worker       else
8502*7304104dSAndroid Build Coastguard Worker 	++level;
8503*7304104dSAndroid Build Coastguard Worker     }
8504*7304104dSAndroid Build Coastguard Worker   while (level >= 0);
8505*7304104dSAndroid Build Coastguard Worker 
8506*7304104dSAndroid Build Coastguard Worker   /* We might want to show the split compile unit if this was a skeleton.
8507*7304104dSAndroid Build Coastguard Worker      We need to scan it if we are requesting printing .debug_ranges for
8508*7304104dSAndroid Build Coastguard Worker      DWARF4 since GNU DebugFission uses "offsets" into the main ranges
8509*7304104dSAndroid Build Coastguard Worker      section.  */
8510*7304104dSAndroid Build Coastguard Worker   if (unit_type == DW_UT_skeleton
8511*7304104dSAndroid Build Coastguard Worker       && ((!silent && show_split_units)
8512*7304104dSAndroid Build Coastguard Worker 	  || (version < 5 && (print_debug_sections & section_ranges) != 0)))
8513*7304104dSAndroid Build Coastguard Worker     {
8514*7304104dSAndroid Build Coastguard Worker       Dwarf_Die subdie;
8515*7304104dSAndroid Build Coastguard Worker       if (dwarf_cu_info (cu, NULL, NULL, NULL, &subdie, NULL, NULL, NULL) != 0
8516*7304104dSAndroid Build Coastguard Worker 	  || dwarf_tag (&subdie) == DW_TAG_invalid)
8517*7304104dSAndroid Build Coastguard Worker 	{
8518*7304104dSAndroid Build Coastguard Worker 	  if (!silent)
8519*7304104dSAndroid Build Coastguard Worker 	    {
8520*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Attribute dwo_at;
8521*7304104dSAndroid Build Coastguard Worker 	      const char *dwo_name =
8522*7304104dSAndroid Build Coastguard Worker 		(dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name,
8523*7304104dSAndroid Build Coastguard Worker 					       &dwo_at))
8524*7304104dSAndroid Build Coastguard Worker 		 ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name,
8525*7304104dSAndroid Build Coastguard Worker 						   &dwo_at))
8526*7304104dSAndroid Build Coastguard Worker 		     ?: "<unknown>"));
8527*7304104dSAndroid Build Coastguard Worker 	      fprintf (stderr,
8528*7304104dSAndroid Build Coastguard Worker 		       "Could not find split unit '%s', id: %" PRIx64 "\n",
8529*7304104dSAndroid Build Coastguard Worker 		       dwo_name, unit_id);
8530*7304104dSAndroid Build Coastguard Worker 	    }
8531*7304104dSAndroid Build Coastguard Worker 	}
8532*7304104dSAndroid Build Coastguard Worker       else
8533*7304104dSAndroid Build Coastguard Worker 	{
8534*7304104dSAndroid Build Coastguard Worker 	  Dwarf_CU *split_cu = subdie.cu;
8535*7304104dSAndroid Build Coastguard Worker 	  dwarf_cu_die (split_cu, &result, NULL, &abbroffset,
8536*7304104dSAndroid Build Coastguard Worker 			&addrsize, &offsize, &unit_id, &subdie_off);
8537*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off offset = cu->start;
8538*7304104dSAndroid Build Coastguard Worker 
8539*7304104dSAndroid Build Coastguard Worker 	  if (!silent)
8540*7304104dSAndroid Build Coastguard Worker 	    {
8541*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Split compilation unit at offset %"
8542*7304104dSAndroid Build Coastguard Worker 			       PRIu64 ":\n"
8543*7304104dSAndroid Build Coastguard Worker 			       " Version: %" PRIu16
8544*7304104dSAndroid Build Coastguard Worker 			       ", Abbreviation section offset: %" PRIu64
8545*7304104dSAndroid Build Coastguard Worker 			       ", Address size: %" PRIu8
8546*7304104dSAndroid Build Coastguard Worker 			       ", Offset size: %" PRIu8 "\n"),
8547*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) offset, version, abbroffset,
8548*7304104dSAndroid Build Coastguard Worker 		      addrsize, offsize);
8549*7304104dSAndroid Build Coastguard Worker 	      printf (_(" Unit type: %s (%" PRIu8 ")"),
8550*7304104dSAndroid Build Coastguard Worker 		      dwarf_unit_name (unit_type), unit_type);
8551*7304104dSAndroid Build Coastguard Worker 	      printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
8552*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
8553*7304104dSAndroid Build Coastguard Worker 	    }
8554*7304104dSAndroid Build Coastguard Worker 
8555*7304104dSAndroid Build Coastguard Worker 	  unit_type = DW_UT_split_compile;
8556*7304104dSAndroid Build Coastguard Worker 	  is_split = true;
8557*7304104dSAndroid Build Coastguard Worker 	  level = 0;
8558*7304104dSAndroid Build Coastguard Worker 	  dies[0] = subdie;
8559*7304104dSAndroid Build Coastguard Worker 	  args.cu = dies[0].cu;
8560*7304104dSAndroid Build Coastguard Worker 	  args.dbg = split_cu->dbg;
8561*7304104dSAndroid Build Coastguard Worker 	  args.is_split = is_split;
8562*7304104dSAndroid Build Coastguard Worker 	  goto do_cu;
8563*7304104dSAndroid Build Coastguard Worker 	}
8564*7304104dSAndroid Build Coastguard Worker     }
8565*7304104dSAndroid Build Coastguard Worker 
8566*7304104dSAndroid Build Coastguard Worker   /* And again... */
8567*7304104dSAndroid Build Coastguard Worker   goto next_cu;
8568*7304104dSAndroid Build Coastguard Worker 
8569*7304104dSAndroid Build Coastguard Worker  do_return:
8570*7304104dSAndroid Build Coastguard Worker   free (dies);
8571*7304104dSAndroid Build Coastguard Worker }
8572*7304104dSAndroid Build Coastguard Worker 
8573*7304104dSAndroid Build Coastguard Worker static void
print_debug_info_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)8574*7304104dSAndroid Build Coastguard Worker print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
8575*7304104dSAndroid Build Coastguard Worker 			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8576*7304104dSAndroid Build Coastguard Worker {
8577*7304104dSAndroid Build Coastguard Worker   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
8578*7304104dSAndroid Build Coastguard Worker }
8579*7304104dSAndroid Build Coastguard Worker 
8580*7304104dSAndroid Build Coastguard Worker static void
print_debug_types_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)8581*7304104dSAndroid Build Coastguard Worker print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
8582*7304104dSAndroid Build Coastguard Worker 			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8583*7304104dSAndroid Build Coastguard Worker {
8584*7304104dSAndroid Build Coastguard Worker   print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
8585*7304104dSAndroid Build Coastguard Worker }
8586*7304104dSAndroid Build Coastguard Worker 
8587*7304104dSAndroid Build Coastguard Worker 
8588*7304104dSAndroid Build Coastguard Worker static void
print_decoded_line_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)8589*7304104dSAndroid Build Coastguard Worker print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
8590*7304104dSAndroid Build Coastguard Worker 			    GElf_Ehdr *ehdr __attribute__ ((unused)),
8591*7304104dSAndroid Build Coastguard Worker 			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8592*7304104dSAndroid Build Coastguard Worker {
8593*7304104dSAndroid Build Coastguard Worker   printf (_("\
8594*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
8595*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
8596*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
8597*7304104dSAndroid Build Coastguard Worker 
8598*7304104dSAndroid Build Coastguard Worker   size_t address_size
8599*7304104dSAndroid Build Coastguard Worker     = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
8600*7304104dSAndroid Build Coastguard Worker 
8601*7304104dSAndroid Build Coastguard Worker   Dwarf_Lines *lines;
8602*7304104dSAndroid Build Coastguard Worker   size_t nlines;
8603*7304104dSAndroid Build Coastguard Worker   Dwarf_Off off, next_off = 0;
8604*7304104dSAndroid Build Coastguard Worker   Dwarf_CU *cu = NULL;
8605*7304104dSAndroid Build Coastguard Worker   while (dwarf_next_lines (dbg, off = next_off, &next_off, &cu, NULL, NULL,
8606*7304104dSAndroid Build Coastguard Worker 			   &lines, &nlines) == 0)
8607*7304104dSAndroid Build Coastguard Worker     {
8608*7304104dSAndroid Build Coastguard Worker       Dwarf_Die cudie;
8609*7304104dSAndroid Build Coastguard Worker       if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
8610*7304104dSAndroid Build Coastguard Worker 				       NULL, NULL, NULL, NULL) == 0)
8611*7304104dSAndroid Build Coastguard Worker 	printf (" CU [%" PRIx64 "] %s\n",
8612*7304104dSAndroid Build Coastguard Worker 		dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
8613*7304104dSAndroid Build Coastguard Worker       else
8614*7304104dSAndroid Build Coastguard Worker 	{
8615*7304104dSAndroid Build Coastguard Worker 	  /* DWARF5 lines can be independent of any CU, but they probably
8616*7304104dSAndroid Build Coastguard Worker 	     are used by some CU.  Determine the CU this block is for.  */
8617*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off cuoffset;
8618*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off ncuoffset = 0;
8619*7304104dSAndroid Build Coastguard Worker 	  size_t hsize;
8620*7304104dSAndroid Build Coastguard Worker 	  while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
8621*7304104dSAndroid Build Coastguard Worker 			       NULL, NULL, NULL) == 0)
8622*7304104dSAndroid Build Coastguard Worker 	    {
8623*7304104dSAndroid Build Coastguard Worker 	      if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
8624*7304104dSAndroid Build Coastguard Worker 		continue;
8625*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Attribute stmt_list;
8626*7304104dSAndroid Build Coastguard Worker 	      if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
8627*7304104dSAndroid Build Coastguard Worker 		continue;
8628*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Word lineoff;
8629*7304104dSAndroid Build Coastguard Worker 	      if (dwarf_formudata (&stmt_list, &lineoff) != 0)
8630*7304104dSAndroid Build Coastguard Worker 		continue;
8631*7304104dSAndroid Build Coastguard Worker 	      if (lineoff == off)
8632*7304104dSAndroid Build Coastguard Worker 		{
8633*7304104dSAndroid Build Coastguard Worker 		  /* Found the CU.  */
8634*7304104dSAndroid Build Coastguard Worker 		  cu = cudie.cu;
8635*7304104dSAndroid Build Coastguard Worker 		  break;
8636*7304104dSAndroid Build Coastguard Worker 		}
8637*7304104dSAndroid Build Coastguard Worker 	    }
8638*7304104dSAndroid Build Coastguard Worker 
8639*7304104dSAndroid Build Coastguard Worker 	  if (cu != NULL)
8640*7304104dSAndroid Build Coastguard Worker 	    printf (" CU [%" PRIx64 "] %s\n",
8641*7304104dSAndroid Build Coastguard Worker 		    dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
8642*7304104dSAndroid Build Coastguard Worker 	  else
8643*7304104dSAndroid Build Coastguard Worker 	    printf (" No CU\n");
8644*7304104dSAndroid Build Coastguard Worker 	}
8645*7304104dSAndroid Build Coastguard Worker 
8646*7304104dSAndroid Build Coastguard Worker       printf ("  line:col SBPE* disc isa op address"
8647*7304104dSAndroid Build Coastguard Worker 	      " (Statement Block Prologue Epilogue *End)\n");
8648*7304104dSAndroid Build Coastguard Worker       const char *last_file = "";
8649*7304104dSAndroid Build Coastguard Worker       for (size_t n = 0; n < nlines; n++)
8650*7304104dSAndroid Build Coastguard Worker 	{
8651*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Line *line = dwarf_onesrcline (lines, n);
8652*7304104dSAndroid Build Coastguard Worker 	  if (line == NULL)
8653*7304104dSAndroid Build Coastguard Worker 	    {
8654*7304104dSAndroid Build Coastguard Worker 	      printf ("  dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
8655*7304104dSAndroid Build Coastguard Worker 	      continue;
8656*7304104dSAndroid Build Coastguard Worker 	    }
8657*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word mtime, length;
8658*7304104dSAndroid Build Coastguard Worker 	  const char *file = dwarf_linesrc (line, &mtime, &length);
8659*7304104dSAndroid Build Coastguard Worker 	  if (file == NULL)
8660*7304104dSAndroid Build Coastguard Worker 	    {
8661*7304104dSAndroid Build Coastguard Worker 	      printf ("  <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
8662*7304104dSAndroid Build Coastguard Worker 	      last_file = "";
8663*7304104dSAndroid Build Coastguard Worker 	    }
8664*7304104dSAndroid Build Coastguard Worker 	  else if (strcmp (last_file, file) != 0)
8665*7304104dSAndroid Build Coastguard Worker 	    {
8666*7304104dSAndroid Build Coastguard Worker 	      printf ("  %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
8667*7304104dSAndroid Build Coastguard Worker 		      file, mtime, length);
8668*7304104dSAndroid Build Coastguard Worker 	      last_file = file;
8669*7304104dSAndroid Build Coastguard Worker 	    }
8670*7304104dSAndroid Build Coastguard Worker 
8671*7304104dSAndroid Build Coastguard Worker 	  int lineno, colno;
8672*7304104dSAndroid Build Coastguard Worker 	  bool statement, endseq, block, prologue_end, epilogue_begin;
8673*7304104dSAndroid Build Coastguard Worker 	  unsigned int lineop, isa, disc;
8674*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Addr address;
8675*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineaddr (line, &address);
8676*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineno (line, &lineno);
8677*7304104dSAndroid Build Coastguard Worker 	  dwarf_linecol (line, &colno);
8678*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineop_index (line, &lineop);
8679*7304104dSAndroid Build Coastguard Worker 	  dwarf_linebeginstatement (line, &statement);
8680*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineendsequence (line, &endseq);
8681*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineblock (line, &block);
8682*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineprologueend (line, &prologue_end);
8683*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineepiloguebegin (line, &epilogue_begin);
8684*7304104dSAndroid Build Coastguard Worker 	  dwarf_lineisa (line, &isa);
8685*7304104dSAndroid Build Coastguard Worker 	  dwarf_linediscriminator (line, &disc);
8686*7304104dSAndroid Build Coastguard Worker 
8687*7304104dSAndroid Build Coastguard Worker 	  /* End sequence is special, it is one byte past.  */
8688*7304104dSAndroid Build Coastguard Worker 	  printf ("  %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
8689*7304104dSAndroid Build Coastguard Worker 		  lineno, colno,
8690*7304104dSAndroid Build Coastguard Worker 		  (statement ? 'S' : ' '),
8691*7304104dSAndroid Build Coastguard Worker 		  (block ? 'B' : ' '),
8692*7304104dSAndroid Build Coastguard Worker 		  (prologue_end ? 'P' : ' '),
8693*7304104dSAndroid Build Coastguard Worker 		  (epilogue_begin ? 'E' : ' '),
8694*7304104dSAndroid Build Coastguard Worker 		  (endseq ? '*' : ' '),
8695*7304104dSAndroid Build Coastguard Worker 		  disc, isa, lineop);
8696*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size,
8697*7304104dSAndroid Build Coastguard Worker 			    address - (endseq ? 1 : 0), address);
8698*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
8699*7304104dSAndroid Build Coastguard Worker 
8700*7304104dSAndroid Build Coastguard Worker 	  if (endseq)
8701*7304104dSAndroid Build Coastguard Worker 	    printf("\n");
8702*7304104dSAndroid Build Coastguard Worker 	}
8703*7304104dSAndroid Build Coastguard Worker     }
8704*7304104dSAndroid Build Coastguard Worker }
8705*7304104dSAndroid Build Coastguard Worker 
8706*7304104dSAndroid Build Coastguard Worker 
8707*7304104dSAndroid Build Coastguard Worker /* Print the value of a form.
8708*7304104dSAndroid Build Coastguard Worker    Returns new value of readp, or readendp on failure.  */
8709*7304104dSAndroid Build Coastguard Worker static const unsigned char *
print_form_data(Dwarf * dbg,int form,const unsigned char * readp,const unsigned char * readendp,unsigned int offset_len,Dwarf_Off str_offsets_base)8710*7304104dSAndroid Build Coastguard Worker print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
8711*7304104dSAndroid Build Coastguard Worker 		 const unsigned char *readendp, unsigned int offset_len,
8712*7304104dSAndroid Build Coastguard Worker 		 Dwarf_Off str_offsets_base)
8713*7304104dSAndroid Build Coastguard Worker {
8714*7304104dSAndroid Build Coastguard Worker   Dwarf_Word val;
8715*7304104dSAndroid Build Coastguard Worker   unsigned char *endp;
8716*7304104dSAndroid Build Coastguard Worker   Elf_Data *data;
8717*7304104dSAndroid Build Coastguard Worker   char *str;
8718*7304104dSAndroid Build Coastguard Worker   switch (form)
8719*7304104dSAndroid Build Coastguard Worker     {
8720*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data1:
8721*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8722*7304104dSAndroid Build Coastguard Worker 	{
8723*7304104dSAndroid Build Coastguard Worker 	invalid_data:
8724*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, "invalid data");
8725*7304104dSAndroid Build Coastguard Worker 	  return readendp;
8726*7304104dSAndroid Build Coastguard Worker 	}
8727*7304104dSAndroid Build Coastguard Worker       val = *readp++;
8728*7304104dSAndroid Build Coastguard Worker       printf (" %" PRIx8, (unsigned int) val);
8729*7304104dSAndroid Build Coastguard Worker       break;
8730*7304104dSAndroid Build Coastguard Worker 
8731*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data2:
8732*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 2)
8733*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8734*7304104dSAndroid Build Coastguard Worker       val = read_2ubyte_unaligned_inc (dbg, readp);
8735*7304104dSAndroid Build Coastguard Worker       printf(" %" PRIx16, (unsigned int) val);
8736*7304104dSAndroid Build Coastguard Worker       break;
8737*7304104dSAndroid Build Coastguard Worker 
8738*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data4:
8739*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 4)
8740*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8741*7304104dSAndroid Build Coastguard Worker       val = read_4ubyte_unaligned_inc (dbg, readp);
8742*7304104dSAndroid Build Coastguard Worker       printf (" %" PRIx32, (unsigned int) val);
8743*7304104dSAndroid Build Coastguard Worker       break;
8744*7304104dSAndroid Build Coastguard Worker 
8745*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data8:
8746*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 8)
8747*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8748*7304104dSAndroid Build Coastguard Worker       val = read_8ubyte_unaligned_inc (dbg, readp);
8749*7304104dSAndroid Build Coastguard Worker       printf (" %" PRIx64, val);
8750*7304104dSAndroid Build Coastguard Worker       break;
8751*7304104dSAndroid Build Coastguard Worker 
8752*7304104dSAndroid Build Coastguard Worker     case DW_FORM_sdata:
8753*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8754*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8755*7304104dSAndroid Build Coastguard Worker       get_sleb128 (val, readp, readendp);
8756*7304104dSAndroid Build Coastguard Worker       printf (" %" PRIx64, val);
8757*7304104dSAndroid Build Coastguard Worker       break;
8758*7304104dSAndroid Build Coastguard Worker 
8759*7304104dSAndroid Build Coastguard Worker     case DW_FORM_udata:
8760*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8761*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8762*7304104dSAndroid Build Coastguard Worker       get_uleb128 (val, readp, readendp);
8763*7304104dSAndroid Build Coastguard Worker       printf (" %" PRIx64, val);
8764*7304104dSAndroid Build Coastguard Worker       break;
8765*7304104dSAndroid Build Coastguard Worker 
8766*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block:
8767*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8768*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8769*7304104dSAndroid Build Coastguard Worker       get_uleb128 (val, readp, readendp);
8770*7304104dSAndroid Build Coastguard Worker       if ((size_t) (readendp - readp) < val)
8771*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8772*7304104dSAndroid Build Coastguard Worker       print_bytes (val, readp);
8773*7304104dSAndroid Build Coastguard Worker       readp += val;
8774*7304104dSAndroid Build Coastguard Worker       break;
8775*7304104dSAndroid Build Coastguard Worker 
8776*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block1:
8777*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8778*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8779*7304104dSAndroid Build Coastguard Worker       val = *readp++;
8780*7304104dSAndroid Build Coastguard Worker       if ((size_t) (readendp - readp) < val)
8781*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8782*7304104dSAndroid Build Coastguard Worker       print_bytes (val, readp);
8783*7304104dSAndroid Build Coastguard Worker       readp += val;
8784*7304104dSAndroid Build Coastguard Worker       break;
8785*7304104dSAndroid Build Coastguard Worker 
8786*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block2:
8787*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 2)
8788*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8789*7304104dSAndroid Build Coastguard Worker       val = read_2ubyte_unaligned_inc (dbg, readp);
8790*7304104dSAndroid Build Coastguard Worker       if ((size_t) (readendp - readp) < val)
8791*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8792*7304104dSAndroid Build Coastguard Worker       print_bytes (val, readp);
8793*7304104dSAndroid Build Coastguard Worker       readp += val;
8794*7304104dSAndroid Build Coastguard Worker       break;
8795*7304104dSAndroid Build Coastguard Worker 
8796*7304104dSAndroid Build Coastguard Worker     case DW_FORM_block4:
8797*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 4)
8798*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8799*7304104dSAndroid Build Coastguard Worker       val = read_4ubyte_unaligned_inc (dbg, readp);
8800*7304104dSAndroid Build Coastguard Worker       if ((size_t) (readendp - readp) < val)
8801*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8802*7304104dSAndroid Build Coastguard Worker       print_bytes (val, readp);
8803*7304104dSAndroid Build Coastguard Worker       readp += val;
8804*7304104dSAndroid Build Coastguard Worker       break;
8805*7304104dSAndroid Build Coastguard Worker 
8806*7304104dSAndroid Build Coastguard Worker     case DW_FORM_data16:
8807*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 16)
8808*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8809*7304104dSAndroid Build Coastguard Worker       print_bytes (16, readp);
8810*7304104dSAndroid Build Coastguard Worker       readp += 16;
8811*7304104dSAndroid Build Coastguard Worker       break;
8812*7304104dSAndroid Build Coastguard Worker 
8813*7304104dSAndroid Build Coastguard Worker     case DW_FORM_flag:
8814*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8815*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8816*7304104dSAndroid Build Coastguard Worker       val = *readp++;
8817*7304104dSAndroid Build Coastguard Worker       printf ("%s", val != 0 ? yes_str : no_str);
8818*7304104dSAndroid Build Coastguard Worker       break;
8819*7304104dSAndroid Build Coastguard Worker 
8820*7304104dSAndroid Build Coastguard Worker     case DW_FORM_string:
8821*7304104dSAndroid Build Coastguard Worker       endp = memchr (readp, '\0', readendp - readp);
8822*7304104dSAndroid Build Coastguard Worker       if (endp == NULL)
8823*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8824*7304104dSAndroid Build Coastguard Worker       printf ("%s", readp);
8825*7304104dSAndroid Build Coastguard Worker       readp = endp + 1;
8826*7304104dSAndroid Build Coastguard Worker       break;
8827*7304104dSAndroid Build Coastguard Worker 
8828*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strp:
8829*7304104dSAndroid Build Coastguard Worker     case DW_FORM_line_strp:
8830*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strp_sup:
8831*7304104dSAndroid Build Coastguard Worker       if ((size_t) (readendp - readp) < offset_len)
8832*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8833*7304104dSAndroid Build Coastguard Worker       if (offset_len == 8)
8834*7304104dSAndroid Build Coastguard Worker 	val = read_8ubyte_unaligned_inc (dbg, readp);
8835*7304104dSAndroid Build Coastguard Worker       else
8836*7304104dSAndroid Build Coastguard Worker 	val = read_4ubyte_unaligned_inc (dbg, readp);
8837*7304104dSAndroid Build Coastguard Worker       if (form == DW_FORM_strp)
8838*7304104dSAndroid Build Coastguard Worker 	data = dbg->sectiondata[IDX_debug_str];
8839*7304104dSAndroid Build Coastguard Worker       else if (form == DW_FORM_line_strp)
8840*7304104dSAndroid Build Coastguard Worker 	data = dbg->sectiondata[IDX_debug_line_str];
8841*7304104dSAndroid Build Coastguard Worker       else /* form == DW_FORM_strp_sup */
8842*7304104dSAndroid Build Coastguard Worker 	{
8843*7304104dSAndroid Build Coastguard Worker 	  Dwarf *alt = dwarf_getalt (dbg);
8844*7304104dSAndroid Build Coastguard Worker 	  data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL;
8845*7304104dSAndroid Build Coastguard Worker 	}
8846*7304104dSAndroid Build Coastguard Worker       if (data == NULL || val >= data->d_size
8847*7304104dSAndroid Build Coastguard Worker 	  || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL)
8848*7304104dSAndroid Build Coastguard Worker 	str = "???";
8849*7304104dSAndroid Build Coastguard Worker       else
8850*7304104dSAndroid Build Coastguard Worker 	str = (char *) data->d_buf + val;
8851*7304104dSAndroid Build Coastguard Worker       printf ("%s (%" PRIu64 ")", str, val);
8852*7304104dSAndroid Build Coastguard Worker       break;
8853*7304104dSAndroid Build Coastguard Worker 
8854*7304104dSAndroid Build Coastguard Worker     case DW_FORM_sec_offset:
8855*7304104dSAndroid Build Coastguard Worker       if ((size_t) (readendp - readp) < offset_len)
8856*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8857*7304104dSAndroid Build Coastguard Worker       if (offset_len == 8)
8858*7304104dSAndroid Build Coastguard Worker 	val = read_8ubyte_unaligned_inc (dbg, readp);
8859*7304104dSAndroid Build Coastguard Worker       else
8860*7304104dSAndroid Build Coastguard Worker 	val = read_4ubyte_unaligned_inc (dbg, readp);
8861*7304104dSAndroid Build Coastguard Worker       printf ("[%" PRIx64 "]", val);
8862*7304104dSAndroid Build Coastguard Worker       break;
8863*7304104dSAndroid Build Coastguard Worker 
8864*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx:
8865*7304104dSAndroid Build Coastguard Worker     case DW_FORM_GNU_str_index:
8866*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8867*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8868*7304104dSAndroid Build Coastguard Worker       get_uleb128 (val, readp, readendp);
8869*7304104dSAndroid Build Coastguard Worker     strx_val:
8870*7304104dSAndroid Build Coastguard Worker       data = dbg->sectiondata[IDX_debug_str_offsets];
8871*7304104dSAndroid Build Coastguard Worker       if (data == NULL
8872*7304104dSAndroid Build Coastguard Worker 	  || data->d_size - str_offsets_base < val)
8873*7304104dSAndroid Build Coastguard Worker 	str = "???";
8874*7304104dSAndroid Build Coastguard Worker       else
8875*7304104dSAndroid Build Coastguard Worker 	{
8876*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *strreadp = data->d_buf + str_offsets_base + val;
8877*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *strreadendp = data->d_buf + data->d_size;
8878*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (strreadendp - strreadp) < offset_len)
8879*7304104dSAndroid Build Coastguard Worker 	    str = "???";
8880*7304104dSAndroid Build Coastguard Worker 	  else
8881*7304104dSAndroid Build Coastguard Worker 	    {
8882*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Off idx;
8883*7304104dSAndroid Build Coastguard Worker 	      if (offset_len == 8)
8884*7304104dSAndroid Build Coastguard Worker 		idx = read_8ubyte_unaligned (dbg, strreadp);
8885*7304104dSAndroid Build Coastguard Worker 	      else
8886*7304104dSAndroid Build Coastguard Worker 		idx = read_4ubyte_unaligned (dbg, strreadp);
8887*7304104dSAndroid Build Coastguard Worker 
8888*7304104dSAndroid Build Coastguard Worker 	      data = dbg->sectiondata[IDX_debug_str];
8889*7304104dSAndroid Build Coastguard Worker 	      if (data == NULL || idx >= data->d_size
8890*7304104dSAndroid Build Coastguard Worker 		  || memchr (data->d_buf + idx, '\0',
8891*7304104dSAndroid Build Coastguard Worker 			     data->d_size - idx) == NULL)
8892*7304104dSAndroid Build Coastguard Worker 		str = "???";
8893*7304104dSAndroid Build Coastguard Worker 	      else
8894*7304104dSAndroid Build Coastguard Worker 		str = (char *) data->d_buf + idx;
8895*7304104dSAndroid Build Coastguard Worker 	    }
8896*7304104dSAndroid Build Coastguard Worker 	}
8897*7304104dSAndroid Build Coastguard Worker       printf ("%s (%" PRIu64 ")", str, val);
8898*7304104dSAndroid Build Coastguard Worker       break;
8899*7304104dSAndroid Build Coastguard Worker 
8900*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx1:
8901*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 1)
8902*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8903*7304104dSAndroid Build Coastguard Worker       val = *readp++;
8904*7304104dSAndroid Build Coastguard Worker       goto strx_val;
8905*7304104dSAndroid Build Coastguard Worker 
8906*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx2:
8907*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 2)
8908*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8909*7304104dSAndroid Build Coastguard Worker       val = read_2ubyte_unaligned_inc (dbg, readp);
8910*7304104dSAndroid Build Coastguard Worker       goto strx_val;
8911*7304104dSAndroid Build Coastguard Worker 
8912*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx3:
8913*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 3)
8914*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8915*7304104dSAndroid Build Coastguard Worker       val = read_3ubyte_unaligned_inc (dbg, readp);
8916*7304104dSAndroid Build Coastguard Worker       goto strx_val;
8917*7304104dSAndroid Build Coastguard Worker 
8918*7304104dSAndroid Build Coastguard Worker     case DW_FORM_strx4:
8919*7304104dSAndroid Build Coastguard Worker       if (readendp - readp < 4)
8920*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8921*7304104dSAndroid Build Coastguard Worker       val = read_4ubyte_unaligned_inc (dbg, readp);
8922*7304104dSAndroid Build Coastguard Worker       goto strx_val;
8923*7304104dSAndroid Build Coastguard Worker 
8924*7304104dSAndroid Build Coastguard Worker     default:
8925*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("unknown form: %s"), dwarf_form_name (form));
8926*7304104dSAndroid Build Coastguard Worker       return readendp;
8927*7304104dSAndroid Build Coastguard Worker     }
8928*7304104dSAndroid Build Coastguard Worker 
8929*7304104dSAndroid Build Coastguard Worker   return readp;
8930*7304104dSAndroid Build Coastguard Worker }
8931*7304104dSAndroid Build Coastguard Worker 
8932*7304104dSAndroid Build Coastguard Worker /* Only used via run_advance_pc() macro */
8933*7304104dSAndroid Build Coastguard Worker static inline void
run_advance_pc(unsigned int op_advance,unsigned int minimum_instr_len,unsigned int max_ops_per_instr,unsigned int * op_addr_advance,Dwarf_Word * address,unsigned int * op_index)8934*7304104dSAndroid Build Coastguard Worker run_advance_pc (unsigned int op_advance,
8935*7304104dSAndroid Build Coastguard Worker                 unsigned int minimum_instr_len,
8936*7304104dSAndroid Build Coastguard Worker                 unsigned int max_ops_per_instr,
8937*7304104dSAndroid Build Coastguard Worker                 unsigned int *op_addr_advance,
8938*7304104dSAndroid Build Coastguard Worker                 Dwarf_Word *address,
8939*7304104dSAndroid Build Coastguard Worker                 unsigned int *op_index)
8940*7304104dSAndroid Build Coastguard Worker {
8941*7304104dSAndroid Build Coastguard Worker   const unsigned int advanced_op_index = (*op_index) + op_advance;
8942*7304104dSAndroid Build Coastguard Worker 
8943*7304104dSAndroid Build Coastguard Worker   *op_addr_advance = minimum_instr_len * (advanced_op_index
8944*7304104dSAndroid Build Coastguard Worker                                          / max_ops_per_instr);
8945*7304104dSAndroid Build Coastguard Worker   *address = *address + *op_addr_advance;
8946*7304104dSAndroid Build Coastguard Worker   *op_index = advanced_op_index % max_ops_per_instr;
8947*7304104dSAndroid Build Coastguard Worker }
8948*7304104dSAndroid Build Coastguard Worker 
8949*7304104dSAndroid Build Coastguard Worker static void
print_debug_line_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)8950*7304104dSAndroid Build Coastguard Worker print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
8951*7304104dSAndroid Build Coastguard Worker 			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
8952*7304104dSAndroid Build Coastguard Worker {
8953*7304104dSAndroid Build Coastguard Worker   if (decodedline)
8954*7304104dSAndroid Build Coastguard Worker     {
8955*7304104dSAndroid Build Coastguard Worker       print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
8956*7304104dSAndroid Build Coastguard Worker       return;
8957*7304104dSAndroid Build Coastguard Worker     }
8958*7304104dSAndroid Build Coastguard Worker 
8959*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_line, scn);
8960*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
8961*7304104dSAndroid Build Coastguard Worker     return;
8962*7304104dSAndroid Build Coastguard Worker 
8963*7304104dSAndroid Build Coastguard Worker   printf (_("\
8964*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
8965*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
8966*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
8967*7304104dSAndroid Build Coastguard Worker 
8968*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_size == 0)
8969*7304104dSAndroid Build Coastguard Worker     return;
8970*7304104dSAndroid Build Coastguard Worker 
8971*7304104dSAndroid Build Coastguard Worker   /* There is no functionality in libdw to read the information in the
8972*7304104dSAndroid Build Coastguard Worker      way it is represented here.  Hardcode the decoder.  */
8973*7304104dSAndroid Build Coastguard Worker 
8974*7304104dSAndroid Build Coastguard Worker   const unsigned char *linep = (const unsigned char *) data->d_buf;
8975*7304104dSAndroid Build Coastguard Worker   const unsigned char *lineendp;
8976*7304104dSAndroid Build Coastguard Worker 
8977*7304104dSAndroid Build Coastguard Worker   while (linep
8978*7304104dSAndroid Build Coastguard Worker 	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
8979*7304104dSAndroid Build Coastguard Worker     {
8980*7304104dSAndroid Build Coastguard Worker       size_t start_offset = linep - (const unsigned char *) data->d_buf;
8981*7304104dSAndroid Build Coastguard Worker 
8982*7304104dSAndroid Build Coastguard Worker       printf (_("\nTable at offset %zu:\n"), start_offset);
8983*7304104dSAndroid Build Coastguard Worker 
8984*7304104dSAndroid Build Coastguard Worker       if (unlikely (linep + 4 > lineendp))
8985*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
8986*7304104dSAndroid Build Coastguard Worker       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
8987*7304104dSAndroid Build Coastguard Worker       unsigned int length = 4;
8988*7304104dSAndroid Build Coastguard Worker       if (unlikely (unit_length == 0xffffffff))
8989*7304104dSAndroid Build Coastguard Worker 	{
8990*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (linep + 8 > lineendp))
8991*7304104dSAndroid Build Coastguard Worker 	    {
8992*7304104dSAndroid Build Coastguard Worker 	    invalid_data:
8993*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("invalid data in section [%zu] '%s'"),
8994*7304104dSAndroid Build Coastguard Worker 		     elf_ndxscn (scn), section_name (ebl, shdr));
8995*7304104dSAndroid Build Coastguard Worker 	      return;
8996*7304104dSAndroid Build Coastguard Worker 	    }
8997*7304104dSAndroid Build Coastguard Worker 	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
8998*7304104dSAndroid Build Coastguard Worker 	  length = 8;
8999*7304104dSAndroid Build Coastguard Worker 	}
9000*7304104dSAndroid Build Coastguard Worker 
9001*7304104dSAndroid Build Coastguard Worker       /* Check whether we have enough room in the section.  */
9002*7304104dSAndroid Build Coastguard Worker       if (unlikely (unit_length > (size_t) (lineendp - linep)))
9003*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
9004*7304104dSAndroid Build Coastguard Worker       lineendp = linep + unit_length;
9005*7304104dSAndroid Build Coastguard Worker 
9006*7304104dSAndroid Build Coastguard Worker       /* The next element of the header is the version identifier.  */
9007*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 2)
9008*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
9009*7304104dSAndroid Build Coastguard Worker       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
9010*7304104dSAndroid Build Coastguard Worker 
9011*7304104dSAndroid Build Coastguard Worker       size_t address_size
9012*7304104dSAndroid Build Coastguard Worker 	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
9013*7304104dSAndroid Build Coastguard Worker       unsigned char segment_selector_size = 0;
9014*7304104dSAndroid Build Coastguard Worker       if (version > 4)
9015*7304104dSAndroid Build Coastguard Worker 	{
9016*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 2)
9017*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9018*7304104dSAndroid Build Coastguard Worker 	  address_size = *linep++;
9019*7304104dSAndroid Build Coastguard Worker 	  segment_selector_size = *linep++;
9020*7304104dSAndroid Build Coastguard Worker 	}
9021*7304104dSAndroid Build Coastguard Worker 
9022*7304104dSAndroid Build Coastguard Worker       /* Next comes the header length.  */
9023*7304104dSAndroid Build Coastguard Worker       Dwarf_Word header_length;
9024*7304104dSAndroid Build Coastguard Worker       if (length == 4)
9025*7304104dSAndroid Build Coastguard Worker 	{
9026*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 4)
9027*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9028*7304104dSAndroid Build Coastguard Worker 	  header_length = read_4ubyte_unaligned_inc (dbg, linep);
9029*7304104dSAndroid Build Coastguard Worker 	}
9030*7304104dSAndroid Build Coastguard Worker       else
9031*7304104dSAndroid Build Coastguard Worker 	{
9032*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 8)
9033*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9034*7304104dSAndroid Build Coastguard Worker 	  header_length = read_8ubyte_unaligned_inc (dbg, linep);
9035*7304104dSAndroid Build Coastguard Worker 	}
9036*7304104dSAndroid Build Coastguard Worker 
9037*7304104dSAndroid Build Coastguard Worker       const unsigned char *header_start = linep;
9038*7304104dSAndroid Build Coastguard Worker 
9039*7304104dSAndroid Build Coastguard Worker       /* Next the minimum instruction length.  */
9040*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 1)
9041*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
9042*7304104dSAndroid Build Coastguard Worker       uint_fast8_t minimum_instr_len = *linep++;
9043*7304104dSAndroid Build Coastguard Worker 
9044*7304104dSAndroid Build Coastguard Worker       /* Next the maximum operations per instruction, in version 4 format.  */
9045*7304104dSAndroid Build Coastguard Worker       uint_fast8_t max_ops_per_instr;
9046*7304104dSAndroid Build Coastguard Worker       if (version < 4)
9047*7304104dSAndroid Build Coastguard Worker 	max_ops_per_instr = 1;
9048*7304104dSAndroid Build Coastguard Worker       else
9049*7304104dSAndroid Build Coastguard Worker 	{
9050*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
9051*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9052*7304104dSAndroid Build Coastguard Worker 	  max_ops_per_instr = *linep++;
9053*7304104dSAndroid Build Coastguard Worker 	}
9054*7304104dSAndroid Build Coastguard Worker 
9055*7304104dSAndroid Build Coastguard Worker       /* We need at least 4 more bytes.  */
9056*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 4)
9057*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
9058*7304104dSAndroid Build Coastguard Worker 
9059*7304104dSAndroid Build Coastguard Worker       /* Then the flag determining the default value of the is_stmt
9060*7304104dSAndroid Build Coastguard Worker 	 register.  */
9061*7304104dSAndroid Build Coastguard Worker       uint_fast8_t default_is_stmt = *linep++;
9062*7304104dSAndroid Build Coastguard Worker 
9063*7304104dSAndroid Build Coastguard Worker       /* Now the line base.  */
9064*7304104dSAndroid Build Coastguard Worker       int_fast8_t line_base = *linep++;
9065*7304104dSAndroid Build Coastguard Worker 
9066*7304104dSAndroid Build Coastguard Worker       /* And the line range.  */
9067*7304104dSAndroid Build Coastguard Worker       uint_fast8_t line_range = *linep++;
9068*7304104dSAndroid Build Coastguard Worker 
9069*7304104dSAndroid Build Coastguard Worker       /* The opcode base.  */
9070*7304104dSAndroid Build Coastguard Worker       uint_fast8_t opcode_base = *linep++;
9071*7304104dSAndroid Build Coastguard Worker 
9072*7304104dSAndroid Build Coastguard Worker       /* Print what we got so far.  */
9073*7304104dSAndroid Build Coastguard Worker       printf (_("\n"
9074*7304104dSAndroid Build Coastguard Worker 		       " Length:                         %" PRIu64 "\n"
9075*7304104dSAndroid Build Coastguard Worker 		       " DWARF version:                  %" PRIuFAST16 "\n"
9076*7304104dSAndroid Build Coastguard Worker 		       " Prologue length:                %" PRIu64 "\n"
9077*7304104dSAndroid Build Coastguard Worker 		       " Address size:                   %zd\n"
9078*7304104dSAndroid Build Coastguard Worker 		       " Segment selector size:          %zd\n"
9079*7304104dSAndroid Build Coastguard Worker 		       " Min instruction length:         %" PRIuFAST8 "\n"
9080*7304104dSAndroid Build Coastguard Worker 		       " Max operations per instruction: %" PRIuFAST8 "\n"
9081*7304104dSAndroid Build Coastguard Worker 		       " Initial value if 'is_stmt':     %" PRIuFAST8 "\n"
9082*7304104dSAndroid Build Coastguard Worker 		       " Line base:                      %" PRIdFAST8 "\n"
9083*7304104dSAndroid Build Coastguard Worker 		       " Line range:                     %" PRIuFAST8 "\n"
9084*7304104dSAndroid Build Coastguard Worker 		       " Opcode base:                    %" PRIuFAST8 "\n"
9085*7304104dSAndroid Build Coastguard Worker 		       "\n"
9086*7304104dSAndroid Build Coastguard Worker 		       "Opcodes:\n"),
9087*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) unit_length, version, (uint64_t) header_length,
9088*7304104dSAndroid Build Coastguard Worker 	      address_size, (size_t) segment_selector_size,
9089*7304104dSAndroid Build Coastguard Worker 	      minimum_instr_len, max_ops_per_instr,
9090*7304104dSAndroid Build Coastguard Worker 	      default_is_stmt, line_base,
9091*7304104dSAndroid Build Coastguard Worker 	      line_range, opcode_base);
9092*7304104dSAndroid Build Coastguard Worker 
9093*7304104dSAndroid Build Coastguard Worker       if (version < 2 || version > 5)
9094*7304104dSAndroid Build Coastguard Worker 	{
9095*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot handle .debug_line version: %u\n"),
9096*7304104dSAndroid Build Coastguard Worker 		 (unsigned int) version);
9097*7304104dSAndroid Build Coastguard Worker 	  linep = lineendp;
9098*7304104dSAndroid Build Coastguard Worker 	  continue;
9099*7304104dSAndroid Build Coastguard Worker 	}
9100*7304104dSAndroid Build Coastguard Worker 
9101*7304104dSAndroid Build Coastguard Worker       if (address_size != 4 && address_size != 8)
9102*7304104dSAndroid Build Coastguard Worker 	{
9103*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot handle address size: %u\n"),
9104*7304104dSAndroid Build Coastguard Worker 		 (unsigned int) address_size);
9105*7304104dSAndroid Build Coastguard Worker 	  linep = lineendp;
9106*7304104dSAndroid Build Coastguard Worker 	  continue;
9107*7304104dSAndroid Build Coastguard Worker 	}
9108*7304104dSAndroid Build Coastguard Worker 
9109*7304104dSAndroid Build Coastguard Worker       if (segment_selector_size != 0)
9110*7304104dSAndroid Build Coastguard Worker 	{
9111*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("cannot handle segment selector size: %u\n"),
9112*7304104dSAndroid Build Coastguard Worker 		 (unsigned int) segment_selector_size);
9113*7304104dSAndroid Build Coastguard Worker 	  linep = lineendp;
9114*7304104dSAndroid Build Coastguard Worker 	  continue;
9115*7304104dSAndroid Build Coastguard Worker 	}
9116*7304104dSAndroid Build Coastguard Worker 
9117*7304104dSAndroid Build Coastguard Worker       if (unlikely (linep + opcode_base - 1 >= lineendp))
9118*7304104dSAndroid Build Coastguard Worker 	{
9119*7304104dSAndroid Build Coastguard Worker 	invalid_unit:
9120*7304104dSAndroid Build Coastguard Worker 	  error (0, 0,
9121*7304104dSAndroid Build Coastguard Worker 		 _("invalid data at offset %tu in section [%zu] '%s'"),
9122*7304104dSAndroid Build Coastguard Worker 		 linep - (const unsigned char *) data->d_buf,
9123*7304104dSAndroid Build Coastguard Worker 		 elf_ndxscn (scn), section_name (ebl, shdr));
9124*7304104dSAndroid Build Coastguard Worker 	  linep = lineendp;
9125*7304104dSAndroid Build Coastguard Worker 	  continue;
9126*7304104dSAndroid Build Coastguard Worker 	}
9127*7304104dSAndroid Build Coastguard Worker       int opcode_base_l10 = 1;
9128*7304104dSAndroid Build Coastguard Worker       unsigned int tmp = opcode_base;
9129*7304104dSAndroid Build Coastguard Worker       while (tmp > 10)
9130*7304104dSAndroid Build Coastguard Worker 	{
9131*7304104dSAndroid Build Coastguard Worker 	  tmp /= 10;
9132*7304104dSAndroid Build Coastguard Worker 	  ++opcode_base_l10;
9133*7304104dSAndroid Build Coastguard Worker 	}
9134*7304104dSAndroid Build Coastguard Worker       const uint8_t *standard_opcode_lengths = linep - 1;
9135*7304104dSAndroid Build Coastguard Worker       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
9136*7304104dSAndroid Build Coastguard Worker 	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
9137*7304104dSAndroid Build Coastguard Worker 			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
9138*7304104dSAndroid Build Coastguard Worker 			  (int) linep[cnt - 1]),
9139*7304104dSAndroid Build Coastguard Worker 		opcode_base_l10, cnt, linep[cnt - 1]);
9140*7304104dSAndroid Build Coastguard Worker       linep += opcode_base - 1;
9141*7304104dSAndroid Build Coastguard Worker 
9142*7304104dSAndroid Build Coastguard Worker       if (unlikely (linep >= lineendp))
9143*7304104dSAndroid Build Coastguard Worker 	goto invalid_unit;
9144*7304104dSAndroid Build Coastguard Worker 
9145*7304104dSAndroid Build Coastguard Worker       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
9146*7304104dSAndroid Build Coastguard Worker 
9147*7304104dSAndroid Build Coastguard Worker       puts (_("\nDirectory table:"));
9148*7304104dSAndroid Build Coastguard Worker       if (version > 4)
9149*7304104dSAndroid Build Coastguard Worker 	{
9150*7304104dSAndroid Build Coastguard Worker 	  struct encpair { uint16_t desc; uint16_t form; };
9151*7304104dSAndroid Build Coastguard Worker 	  struct encpair enc[256];
9152*7304104dSAndroid Build Coastguard Worker 
9153*7304104dSAndroid Build Coastguard Worker 	  printf (_("      ["));
9154*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
9155*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9156*7304104dSAndroid Build Coastguard Worker 	  unsigned char directory_entry_format_count = *linep++;
9157*7304104dSAndroid Build Coastguard Worker 	  for (int i = 0; i < directory_entry_format_count; i++)
9158*7304104dSAndroid Build Coastguard Worker 	    {
9159*7304104dSAndroid Build Coastguard Worker 	      uint16_t desc, form;
9160*7304104dSAndroid Build Coastguard Worker 	      if ((size_t) (lineendp - linep) < 1)
9161*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
9162*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (desc, linep, lineendp);
9163*7304104dSAndroid Build Coastguard Worker 	      if ((size_t) (lineendp - linep) < 1)
9164*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
9165*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (form, linep, lineendp);
9166*7304104dSAndroid Build Coastguard Worker 
9167*7304104dSAndroid Build Coastguard Worker 	      enc[i].desc = desc;
9168*7304104dSAndroid Build Coastguard Worker 	      enc[i].form = form;
9169*7304104dSAndroid Build Coastguard Worker 
9170*7304104dSAndroid Build Coastguard Worker 	      printf ("%s(%s)",
9171*7304104dSAndroid Build Coastguard Worker 		      dwarf_line_content_description_name (desc),
9172*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form));
9173*7304104dSAndroid Build Coastguard Worker 	      if (i + 1 < directory_entry_format_count)
9174*7304104dSAndroid Build Coastguard Worker 		printf (", ");
9175*7304104dSAndroid Build Coastguard Worker 	    }
9176*7304104dSAndroid Build Coastguard Worker 	  printf ("]\n");
9177*7304104dSAndroid Build Coastguard Worker 
9178*7304104dSAndroid Build Coastguard Worker 	  uint64_t directories_count;
9179*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
9180*7304104dSAndroid Build Coastguard Worker             goto invalid_data;
9181*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (directories_count, linep, lineendp);
9182*7304104dSAndroid Build Coastguard Worker 
9183*7304104dSAndroid Build Coastguard Worker 	  if (directory_entry_format_count == 0
9184*7304104dSAndroid Build Coastguard Worker 	      && directories_count != 0)
9185*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9186*7304104dSAndroid Build Coastguard Worker 
9187*7304104dSAndroid Build Coastguard Worker 	  for (uint64_t i = 0; i < directories_count; i++)
9188*7304104dSAndroid Build Coastguard Worker 	    {
9189*7304104dSAndroid Build Coastguard Worker 	      printf (" %-5" PRIu64 " ", i);
9190*7304104dSAndroid Build Coastguard Worker 	      for (int j = 0; j < directory_entry_format_count; j++)
9191*7304104dSAndroid Build Coastguard Worker 		{
9192*7304104dSAndroid Build Coastguard Worker 		  linep = print_form_data (dbg, enc[j].form,
9193*7304104dSAndroid Build Coastguard Worker 					   linep, lineendp, length,
9194*7304104dSAndroid Build Coastguard Worker 					   str_offsets_base);
9195*7304104dSAndroid Build Coastguard Worker 		  if (j + 1 < directory_entry_format_count)
9196*7304104dSAndroid Build Coastguard Worker 		    printf (", ");
9197*7304104dSAndroid Build Coastguard Worker 		}
9198*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
9199*7304104dSAndroid Build Coastguard Worker 	      if (linep >= lineendp)
9200*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9201*7304104dSAndroid Build Coastguard Worker 	    }
9202*7304104dSAndroid Build Coastguard Worker 	}
9203*7304104dSAndroid Build Coastguard Worker       else
9204*7304104dSAndroid Build Coastguard Worker 	{
9205*7304104dSAndroid Build Coastguard Worker 	  while (linep < lineendp && *linep != 0)
9206*7304104dSAndroid Build Coastguard Worker 	    {
9207*7304104dSAndroid Build Coastguard Worker 	      unsigned char *endp = memchr (linep, '\0', lineendp - linep);
9208*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (endp == NULL))
9209*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9210*7304104dSAndroid Build Coastguard Worker 
9211*7304104dSAndroid Build Coastguard Worker 	      printf (" %s\n", (char *) linep);
9212*7304104dSAndroid Build Coastguard Worker 
9213*7304104dSAndroid Build Coastguard Worker 	      linep = endp + 1;
9214*7304104dSAndroid Build Coastguard Worker 	    }
9215*7304104dSAndroid Build Coastguard Worker 	  if (linep >= lineendp || *linep != 0)
9216*7304104dSAndroid Build Coastguard Worker 	    goto invalid_unit;
9217*7304104dSAndroid Build Coastguard Worker 	  /* Skip the final NUL byte.  */
9218*7304104dSAndroid Build Coastguard Worker 	  ++linep;
9219*7304104dSAndroid Build Coastguard Worker 	}
9220*7304104dSAndroid Build Coastguard Worker 
9221*7304104dSAndroid Build Coastguard Worker       if (unlikely (linep >= lineendp))
9222*7304104dSAndroid Build Coastguard Worker 	goto invalid_unit;
9223*7304104dSAndroid Build Coastguard Worker 
9224*7304104dSAndroid Build Coastguard Worker       puts (_("\nFile name table:"));
9225*7304104dSAndroid Build Coastguard Worker       if (version > 4)
9226*7304104dSAndroid Build Coastguard Worker 	{
9227*7304104dSAndroid Build Coastguard Worker 	  struct encpair { uint16_t desc; uint16_t form; };
9228*7304104dSAndroid Build Coastguard Worker 	  struct encpair enc[256];
9229*7304104dSAndroid Build Coastguard Worker 
9230*7304104dSAndroid Build Coastguard Worker 	  printf (_("      ["));
9231*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
9232*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9233*7304104dSAndroid Build Coastguard Worker 	  unsigned char file_name_format_count = *linep++;
9234*7304104dSAndroid Build Coastguard Worker 	  for (int i = 0; i < file_name_format_count; i++)
9235*7304104dSAndroid Build Coastguard Worker 	    {
9236*7304104dSAndroid Build Coastguard Worker 	      uint64_t desc, form;
9237*7304104dSAndroid Build Coastguard Worker 	      if ((size_t) (lineendp - linep) < 1)
9238*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
9239*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (desc, linep, lineendp);
9240*7304104dSAndroid Build Coastguard Worker 	      if ((size_t) (lineendp - linep) < 1)
9241*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
9242*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (form, linep, lineendp);
9243*7304104dSAndroid Build Coastguard Worker 
9244*7304104dSAndroid Build Coastguard Worker 	      if (! libdw_valid_user_form (form))
9245*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
9246*7304104dSAndroid Build Coastguard Worker 
9247*7304104dSAndroid Build Coastguard Worker 	      enc[i].desc = desc;
9248*7304104dSAndroid Build Coastguard Worker 	      enc[i].form = form;
9249*7304104dSAndroid Build Coastguard Worker 
9250*7304104dSAndroid Build Coastguard Worker 	      printf ("%s(%s)",
9251*7304104dSAndroid Build Coastguard Worker 		      dwarf_line_content_description_name (desc),
9252*7304104dSAndroid Build Coastguard Worker 		      dwarf_form_name (form));
9253*7304104dSAndroid Build Coastguard Worker 	      if (i + 1 < file_name_format_count)
9254*7304104dSAndroid Build Coastguard Worker 		printf (", ");
9255*7304104dSAndroid Build Coastguard Worker 	    }
9256*7304104dSAndroid Build Coastguard Worker 	  printf ("]\n");
9257*7304104dSAndroid Build Coastguard Worker 
9258*7304104dSAndroid Build Coastguard Worker 	  uint64_t file_name_count;
9259*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
9260*7304104dSAndroid Build Coastguard Worker             goto invalid_data;
9261*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (file_name_count, linep, lineendp);
9262*7304104dSAndroid Build Coastguard Worker 
9263*7304104dSAndroid Build Coastguard Worker 	  if (file_name_format_count == 0
9264*7304104dSAndroid Build Coastguard Worker 	      && file_name_count != 0)
9265*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9266*7304104dSAndroid Build Coastguard Worker 
9267*7304104dSAndroid Build Coastguard Worker 	  for (uint64_t i = 0; i < file_name_count; i++)
9268*7304104dSAndroid Build Coastguard Worker 	    {
9269*7304104dSAndroid Build Coastguard Worker 	      printf (" %-5" PRIu64 " ", i);
9270*7304104dSAndroid Build Coastguard Worker 	      for (int j = 0; j < file_name_format_count; j++)
9271*7304104dSAndroid Build Coastguard Worker 		{
9272*7304104dSAndroid Build Coastguard Worker 		  linep = print_form_data (dbg, enc[j].form,
9273*7304104dSAndroid Build Coastguard Worker 					   linep, lineendp, length,
9274*7304104dSAndroid Build Coastguard Worker 					   str_offsets_base);
9275*7304104dSAndroid Build Coastguard Worker 		  if (j + 1 < file_name_format_count)
9276*7304104dSAndroid Build Coastguard Worker 		    printf (", ");
9277*7304104dSAndroid Build Coastguard Worker 		}
9278*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
9279*7304104dSAndroid Build Coastguard Worker 	      if (linep > lineendp)
9280*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9281*7304104dSAndroid Build Coastguard Worker 	    }
9282*7304104dSAndroid Build Coastguard Worker 	}
9283*7304104dSAndroid Build Coastguard Worker       else
9284*7304104dSAndroid Build Coastguard Worker 	{
9285*7304104dSAndroid Build Coastguard Worker 	  puts (_(" Entry Dir   Time      Size      Name"));
9286*7304104dSAndroid Build Coastguard Worker 	  for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
9287*7304104dSAndroid Build Coastguard Worker 	    {
9288*7304104dSAndroid Build Coastguard Worker 	      /* First comes the file name.  */
9289*7304104dSAndroid Build Coastguard Worker 	      char *fname = (char *) linep;
9290*7304104dSAndroid Build Coastguard Worker 	      unsigned char *endp = memchr (fname, '\0', lineendp - linep);
9291*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (endp == NULL))
9292*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9293*7304104dSAndroid Build Coastguard Worker 	      linep = endp + 1;
9294*7304104dSAndroid Build Coastguard Worker 
9295*7304104dSAndroid Build Coastguard Worker 	      /* Then the index.  */
9296*7304104dSAndroid Build Coastguard Worker 	      unsigned int diridx;
9297*7304104dSAndroid Build Coastguard Worker 	      if (lineendp - linep < 1)
9298*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9299*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (diridx, linep, lineendp);
9300*7304104dSAndroid Build Coastguard Worker 
9301*7304104dSAndroid Build Coastguard Worker 	      /* Next comes the modification time.  */
9302*7304104dSAndroid Build Coastguard Worker 	      unsigned int mtime;
9303*7304104dSAndroid Build Coastguard Worker 	      if (lineendp - linep < 1)
9304*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9305*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (mtime, linep, lineendp);
9306*7304104dSAndroid Build Coastguard Worker 
9307*7304104dSAndroid Build Coastguard Worker 	      /* Finally the length of the file.  */
9308*7304104dSAndroid Build Coastguard Worker 	      unsigned int fsize;
9309*7304104dSAndroid Build Coastguard Worker 	      if (lineendp - linep < 1)
9310*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9311*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (fsize, linep, lineendp);
9312*7304104dSAndroid Build Coastguard Worker 
9313*7304104dSAndroid Build Coastguard Worker 	      printf (" %-5u %-5u %-9u %-9u %s\n",
9314*7304104dSAndroid Build Coastguard Worker 		      cnt, diridx, mtime, fsize, fname);
9315*7304104dSAndroid Build Coastguard Worker 	    }
9316*7304104dSAndroid Build Coastguard Worker 	  if (linep >= lineendp || *linep != '\0')
9317*7304104dSAndroid Build Coastguard Worker 	    goto invalid_unit;
9318*7304104dSAndroid Build Coastguard Worker 	  /* Skip the final NUL byte.  */
9319*7304104dSAndroid Build Coastguard Worker 	  ++linep;
9320*7304104dSAndroid Build Coastguard Worker 	}
9321*7304104dSAndroid Build Coastguard Worker 
9322*7304104dSAndroid Build Coastguard Worker       unsigned int debug_str_offset = 0;
9323*7304104dSAndroid Build Coastguard Worker       if (unlikely (linep == header_start + header_length - 4))
9324*7304104dSAndroid Build Coastguard Worker 	{
9325*7304104dSAndroid Build Coastguard Worker 	  /* CUBINs contain an unsigned 4-byte offset */
9326*7304104dSAndroid Build Coastguard Worker 	  debug_str_offset = read_4ubyte_unaligned_inc (dbg, linep);
9327*7304104dSAndroid Build Coastguard Worker 	}
9328*7304104dSAndroid Build Coastguard Worker 
9329*7304104dSAndroid Build Coastguard Worker       if (linep == lineendp)
9330*7304104dSAndroid Build Coastguard Worker 	{
9331*7304104dSAndroid Build Coastguard Worker 	  puts (_("\nNo line number statements."));
9332*7304104dSAndroid Build Coastguard Worker 	  continue;
9333*7304104dSAndroid Build Coastguard Worker 	}
9334*7304104dSAndroid Build Coastguard Worker 
9335*7304104dSAndroid Build Coastguard Worker       puts (_("\nLine number statements:"));
9336*7304104dSAndroid Build Coastguard Worker       Dwarf_Word address = 0;
9337*7304104dSAndroid Build Coastguard Worker       unsigned int op_index = 0;
9338*7304104dSAndroid Build Coastguard Worker       size_t line = 1;
9339*7304104dSAndroid Build Coastguard Worker       uint_fast8_t is_stmt = default_is_stmt;
9340*7304104dSAndroid Build Coastguard Worker 
9341*7304104dSAndroid Build Coastguard Worker       /* Apply the "operation advance" from a special opcode
9342*7304104dSAndroid Build Coastguard Worker 	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
9343*7304104dSAndroid Build Coastguard Worker       unsigned int op_addr_advance;
9344*7304104dSAndroid Build Coastguard Worker #define advance_pc(op_advance) run_advance_pc(op_advance, minimum_instr_len, \
9345*7304104dSAndroid Build Coastguard Worker                       max_ops_per_instr, &op_addr_advance, &address, &op_index)
9346*7304104dSAndroid Build Coastguard Worker 
9347*7304104dSAndroid Build Coastguard Worker       if (max_ops_per_instr == 0)
9348*7304104dSAndroid Build Coastguard Worker 	{
9349*7304104dSAndroid Build Coastguard Worker 	  error (0, 0,
9350*7304104dSAndroid Build Coastguard Worker 		 _("invalid maximum operations per instruction is zero"));
9351*7304104dSAndroid Build Coastguard Worker 	  linep = lineendp;
9352*7304104dSAndroid Build Coastguard Worker 	  continue;
9353*7304104dSAndroid Build Coastguard Worker 	}
9354*7304104dSAndroid Build Coastguard Worker 
9355*7304104dSAndroid Build Coastguard Worker       while (linep < lineendp)
9356*7304104dSAndroid Build Coastguard Worker 	{
9357*7304104dSAndroid Build Coastguard Worker 	  size_t offset = linep - (const unsigned char *) data->d_buf;
9358*7304104dSAndroid Build Coastguard Worker 	  unsigned int u128;
9359*7304104dSAndroid Build Coastguard Worker 	  int s128;
9360*7304104dSAndroid Build Coastguard Worker 
9361*7304104dSAndroid Build Coastguard Worker 	  /* Read the opcode.  */
9362*7304104dSAndroid Build Coastguard Worker 	  unsigned int opcode = *linep++;
9363*7304104dSAndroid Build Coastguard Worker 
9364*7304104dSAndroid Build Coastguard Worker 	  printf (" [%6" PRIx64 "]", (uint64_t)offset);
9365*7304104dSAndroid Build Coastguard Worker 	  /* Is this a special opcode?  */
9366*7304104dSAndroid Build Coastguard Worker 	  if (likely (opcode >= opcode_base))
9367*7304104dSAndroid Build Coastguard Worker 	    {
9368*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (line_range == 0))
9369*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9370*7304104dSAndroid Build Coastguard Worker 
9371*7304104dSAndroid Build Coastguard Worker 	      /* Yes.  Handling this is quite easy since the opcode value
9372*7304104dSAndroid Build Coastguard Worker 		 is computed with
9373*7304104dSAndroid Build Coastguard Worker 
9374*7304104dSAndroid Build Coastguard Worker 		 opcode = (desired line increment - line_base)
9375*7304104dSAndroid Build Coastguard Worker 			   + (line_range * address advance) + opcode_base
9376*7304104dSAndroid Build Coastguard Worker 	      */
9377*7304104dSAndroid Build Coastguard Worker 	      int line_increment = (line_base
9378*7304104dSAndroid Build Coastguard Worker 				    + (opcode - opcode_base) % line_range);
9379*7304104dSAndroid Build Coastguard Worker 
9380*7304104dSAndroid Build Coastguard Worker 	      /* Perform the increments.  */
9381*7304104dSAndroid Build Coastguard Worker 	      line += line_increment;
9382*7304104dSAndroid Build Coastguard Worker 	      advance_pc ((opcode - opcode_base) / line_range);
9383*7304104dSAndroid Build Coastguard Worker 
9384*7304104dSAndroid Build Coastguard Worker 	      printf (_(" special opcode %u: address+%u = "),
9385*7304104dSAndroid Build Coastguard Worker 		      opcode, op_addr_advance);
9386*7304104dSAndroid Build Coastguard Worker 	      print_dwarf_addr (dwflmod, 0, address, address);
9387*7304104dSAndroid Build Coastguard Worker 	      if (op_index > 0)
9388*7304104dSAndroid Build Coastguard Worker 		printf (_(", op_index = %u, line%+d = %zu\n"),
9389*7304104dSAndroid Build Coastguard Worker 			op_index, line_increment, line);
9390*7304104dSAndroid Build Coastguard Worker 	      else
9391*7304104dSAndroid Build Coastguard Worker 		printf (_(", line%+d = %zu\n"),
9392*7304104dSAndroid Build Coastguard Worker 			line_increment, line);
9393*7304104dSAndroid Build Coastguard Worker 	    }
9394*7304104dSAndroid Build Coastguard Worker 	  else if (opcode == 0)
9395*7304104dSAndroid Build Coastguard Worker 	    {
9396*7304104dSAndroid Build Coastguard Worker 	      /* This an extended opcode.  */
9397*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep + 2 > lineendp))
9398*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9399*7304104dSAndroid Build Coastguard Worker 
9400*7304104dSAndroid Build Coastguard Worker 	      /* The length.  */
9401*7304104dSAndroid Build Coastguard Worker 	      unsigned int len = *linep++;
9402*7304104dSAndroid Build Coastguard Worker 
9403*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep + len > lineendp))
9404*7304104dSAndroid Build Coastguard Worker 		goto invalid_unit;
9405*7304104dSAndroid Build Coastguard Worker 
9406*7304104dSAndroid Build Coastguard Worker 	      /* The sub-opcode.  */
9407*7304104dSAndroid Build Coastguard Worker 	      opcode = *linep++;
9408*7304104dSAndroid Build Coastguard Worker 
9409*7304104dSAndroid Build Coastguard Worker 	      printf (_(" extended opcode %u: "), opcode);
9410*7304104dSAndroid Build Coastguard Worker 
9411*7304104dSAndroid Build Coastguard Worker 	      switch (opcode)
9412*7304104dSAndroid Build Coastguard Worker 		{
9413*7304104dSAndroid Build Coastguard Worker 		case DW_LNE_end_sequence:
9414*7304104dSAndroid Build Coastguard Worker 		  puts (_(" end of sequence"));
9415*7304104dSAndroid Build Coastguard Worker 
9416*7304104dSAndroid Build Coastguard Worker 		  /* Reset the registers we care about.  */
9417*7304104dSAndroid Build Coastguard Worker 		  address = 0;
9418*7304104dSAndroid Build Coastguard Worker 		  op_index = 0;
9419*7304104dSAndroid Build Coastguard Worker 		  line = 1;
9420*7304104dSAndroid Build Coastguard Worker 		  is_stmt = default_is_stmt;
9421*7304104dSAndroid Build Coastguard Worker 		  break;
9422*7304104dSAndroid Build Coastguard Worker 
9423*7304104dSAndroid Build Coastguard Worker 		case DW_LNE_set_address:
9424*7304104dSAndroid Build Coastguard Worker 		  op_index = 0;
9425*7304104dSAndroid Build Coastguard Worker 		  if (unlikely ((size_t) (lineendp - linep) < address_size))
9426*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9427*7304104dSAndroid Build Coastguard Worker 		  if (address_size == 4)
9428*7304104dSAndroid Build Coastguard Worker 		    address = read_4ubyte_unaligned_inc (dbg, linep);
9429*7304104dSAndroid Build Coastguard Worker 		  else
9430*7304104dSAndroid Build Coastguard Worker 		    address = read_8ubyte_unaligned_inc (dbg, linep);
9431*7304104dSAndroid Build Coastguard Worker 		  {
9432*7304104dSAndroid Build Coastguard Worker 		    printf (_(" set address to "));
9433*7304104dSAndroid Build Coastguard Worker 		    print_dwarf_addr (dwflmod, 0, address, address);
9434*7304104dSAndroid Build Coastguard Worker 		    printf ("\n");
9435*7304104dSAndroid Build Coastguard Worker 		  }
9436*7304104dSAndroid Build Coastguard Worker 		  break;
9437*7304104dSAndroid Build Coastguard Worker 
9438*7304104dSAndroid Build Coastguard Worker 		case DW_LNE_define_file:
9439*7304104dSAndroid Build Coastguard Worker 		  {
9440*7304104dSAndroid Build Coastguard Worker 		    char *fname = (char *) linep;
9441*7304104dSAndroid Build Coastguard Worker 		    unsigned char *endp = memchr (linep, '\0',
9442*7304104dSAndroid Build Coastguard Worker 						  lineendp - linep);
9443*7304104dSAndroid Build Coastguard Worker 		    if (unlikely (endp == NULL))
9444*7304104dSAndroid Build Coastguard Worker 		      goto invalid_unit;
9445*7304104dSAndroid Build Coastguard Worker 		    linep = endp + 1;
9446*7304104dSAndroid Build Coastguard Worker 
9447*7304104dSAndroid Build Coastguard Worker 		    unsigned int diridx;
9448*7304104dSAndroid Build Coastguard Worker 		    if (lineendp - linep < 1)
9449*7304104dSAndroid Build Coastguard Worker 		      goto invalid_unit;
9450*7304104dSAndroid Build Coastguard Worker 		    get_uleb128 (diridx, linep, lineendp);
9451*7304104dSAndroid Build Coastguard Worker 		    Dwarf_Word mtime;
9452*7304104dSAndroid Build Coastguard Worker 		    if (lineendp - linep < 1)
9453*7304104dSAndroid Build Coastguard Worker 		      goto invalid_unit;
9454*7304104dSAndroid Build Coastguard Worker 		    get_uleb128 (mtime, linep, lineendp);
9455*7304104dSAndroid Build Coastguard Worker 		    Dwarf_Word filelength;
9456*7304104dSAndroid Build Coastguard Worker 		    if (lineendp - linep < 1)
9457*7304104dSAndroid Build Coastguard Worker 		      goto invalid_unit;
9458*7304104dSAndroid Build Coastguard Worker 		    get_uleb128 (filelength, linep, lineendp);
9459*7304104dSAndroid Build Coastguard Worker 
9460*7304104dSAndroid Build Coastguard Worker 		    printf (_("\
9461*7304104dSAndroid Build Coastguard Worker  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
9462*7304104dSAndroid Build Coastguard Worker 			    diridx, (uint64_t) mtime, (uint64_t) filelength,
9463*7304104dSAndroid Build Coastguard Worker 			    fname);
9464*7304104dSAndroid Build Coastguard Worker 		  }
9465*7304104dSAndroid Build Coastguard Worker 		  break;
9466*7304104dSAndroid Build Coastguard Worker 
9467*7304104dSAndroid Build Coastguard Worker 		case DW_LNE_set_discriminator:
9468*7304104dSAndroid Build Coastguard Worker 		  /* Takes one ULEB128 parameter, the discriminator.  */
9469*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (standard_opcode_lengths[opcode] != 1
9470*7304104dSAndroid Build Coastguard Worker 				|| lineendp - linep < 1))
9471*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9472*7304104dSAndroid Build Coastguard Worker 
9473*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (u128, linep, lineendp);
9474*7304104dSAndroid Build Coastguard Worker 		  printf (_(" set discriminator to %u\n"), u128);
9475*7304104dSAndroid Build Coastguard Worker 		  break;
9476*7304104dSAndroid Build Coastguard Worker 
9477*7304104dSAndroid Build Coastguard Worker 		case DW_LNE_NVIDIA_inlined_call:
9478*7304104dSAndroid Build Coastguard Worker 		  {
9479*7304104dSAndroid Build Coastguard Worker 		    if (unlikely (linep >= lineendp))
9480*7304104dSAndroid Build Coastguard Worker 		      goto invalid_data;
9481*7304104dSAndroid Build Coastguard Worker 
9482*7304104dSAndroid Build Coastguard Worker 		    unsigned int context;
9483*7304104dSAndroid Build Coastguard Worker 		    get_uleb128 (context, linep, lineendp);
9484*7304104dSAndroid Build Coastguard Worker 
9485*7304104dSAndroid Build Coastguard Worker 		    if (unlikely (linep >= lineendp))
9486*7304104dSAndroid Build Coastguard Worker 		      goto invalid_data;
9487*7304104dSAndroid Build Coastguard Worker 
9488*7304104dSAndroid Build Coastguard Worker 		    unsigned int function_name;
9489*7304104dSAndroid Build Coastguard Worker 		    get_uleb128 (function_name, linep, lineendp);
9490*7304104dSAndroid Build Coastguard Worker 		    function_name += debug_str_offset;
9491*7304104dSAndroid Build Coastguard Worker 
9492*7304104dSAndroid Build Coastguard Worker 		    Elf_Data *str_data = dbg->sectiondata[IDX_debug_str];
9493*7304104dSAndroid Build Coastguard Worker 		    char *function_str;
9494*7304104dSAndroid Build Coastguard Worker 		    if (str_data == NULL || function_name >= str_data->d_size
9495*7304104dSAndroid Build Coastguard Worker 			|| memchr (str_data->d_buf + function_name, '\0',
9496*7304104dSAndroid Build Coastguard Worker 				   str_data->d_size - function_name) == NULL)
9497*7304104dSAndroid Build Coastguard Worker 		      function_str = "???";
9498*7304104dSAndroid Build Coastguard Worker 		    else
9499*7304104dSAndroid Build Coastguard Worker 		      function_str = (char *) str_data->d_buf + function_name;
9500*7304104dSAndroid Build Coastguard Worker 
9501*7304104dSAndroid Build Coastguard Worker 		    printf (_(" set inlined context %u,"
9502*7304104dSAndroid Build Coastguard Worker 		              " function name %s (0x%x)\n"),
9503*7304104dSAndroid Build Coastguard Worker 			    context, function_str, function_name);
9504*7304104dSAndroid Build Coastguard Worker 		    break;
9505*7304104dSAndroid Build Coastguard Worker 		  }
9506*7304104dSAndroid Build Coastguard Worker 
9507*7304104dSAndroid Build Coastguard Worker 		case DW_LNE_NVIDIA_set_function_name:
9508*7304104dSAndroid Build Coastguard Worker 		  {
9509*7304104dSAndroid Build Coastguard Worker 		    if (unlikely (linep >= lineendp))
9510*7304104dSAndroid Build Coastguard Worker 		      goto invalid_data;
9511*7304104dSAndroid Build Coastguard Worker 
9512*7304104dSAndroid Build Coastguard Worker 		    unsigned int function_name;
9513*7304104dSAndroid Build Coastguard Worker 		    get_uleb128 (function_name, linep, lineendp);
9514*7304104dSAndroid Build Coastguard Worker 		    function_name += debug_str_offset;
9515*7304104dSAndroid Build Coastguard Worker 
9516*7304104dSAndroid Build Coastguard Worker 		    Elf_Data *str_data = dbg->sectiondata[IDX_debug_str];
9517*7304104dSAndroid Build Coastguard Worker 		    char *function_str;
9518*7304104dSAndroid Build Coastguard Worker 		    if (str_data == NULL || function_name >= str_data->d_size
9519*7304104dSAndroid Build Coastguard Worker 			|| memchr (str_data->d_buf + function_name, '\0',
9520*7304104dSAndroid Build Coastguard Worker 				   str_data->d_size - function_name) == NULL)
9521*7304104dSAndroid Build Coastguard Worker 		      function_str = "???";
9522*7304104dSAndroid Build Coastguard Worker 		    else
9523*7304104dSAndroid Build Coastguard Worker 		      function_str = (char *) str_data->d_buf + function_name;
9524*7304104dSAndroid Build Coastguard Worker 
9525*7304104dSAndroid Build Coastguard Worker 		    printf (_(" set function name %s (0x%x)\n"),
9526*7304104dSAndroid Build Coastguard Worker 			    function_str, function_name);
9527*7304104dSAndroid Build Coastguard Worker 		  }
9528*7304104dSAndroid Build Coastguard Worker 		  break;
9529*7304104dSAndroid Build Coastguard Worker 
9530*7304104dSAndroid Build Coastguard Worker 		default:
9531*7304104dSAndroid Build Coastguard Worker 		  /* Unknown, ignore it.  */
9532*7304104dSAndroid Build Coastguard Worker 		  puts (_(" unknown opcode"));
9533*7304104dSAndroid Build Coastguard Worker 		  linep += len - 1;
9534*7304104dSAndroid Build Coastguard Worker 		  break;
9535*7304104dSAndroid Build Coastguard Worker 		}
9536*7304104dSAndroid Build Coastguard Worker 	    }
9537*7304104dSAndroid Build Coastguard Worker 	  else if (opcode <= DW_LNS_set_isa)
9538*7304104dSAndroid Build Coastguard Worker 	    {
9539*7304104dSAndroid Build Coastguard Worker 	      /* This is a known standard opcode.  */
9540*7304104dSAndroid Build Coastguard Worker 	      switch (opcode)
9541*7304104dSAndroid Build Coastguard Worker 		{
9542*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_copy:
9543*7304104dSAndroid Build Coastguard Worker 		  /* Takes no argument.  */
9544*7304104dSAndroid Build Coastguard Worker 		  puts (_(" copy"));
9545*7304104dSAndroid Build Coastguard Worker 		  break;
9546*7304104dSAndroid Build Coastguard Worker 
9547*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_advance_pc:
9548*7304104dSAndroid Build Coastguard Worker 		  /* Takes one uleb128 parameter which is added to the
9549*7304104dSAndroid Build Coastguard Worker 		     address.  */
9550*7304104dSAndroid Build Coastguard Worker 		  if (lineendp - linep < 1)
9551*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9552*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (u128, linep, lineendp);
9553*7304104dSAndroid Build Coastguard Worker 		  advance_pc (u128);
9554*7304104dSAndroid Build Coastguard Worker 		  {
9555*7304104dSAndroid Build Coastguard Worker 		    printf (_(" advance address by %u to "),
9556*7304104dSAndroid Build Coastguard Worker 			    op_addr_advance);
9557*7304104dSAndroid Build Coastguard Worker 		    print_dwarf_addr (dwflmod, 0, address, address);
9558*7304104dSAndroid Build Coastguard Worker 		    if (op_index > 0)
9559*7304104dSAndroid Build Coastguard Worker 		      printf (_(", op_index to %u"), op_index);
9560*7304104dSAndroid Build Coastguard Worker 		    printf ("\n");
9561*7304104dSAndroid Build Coastguard Worker 		  }
9562*7304104dSAndroid Build Coastguard Worker 		  break;
9563*7304104dSAndroid Build Coastguard Worker 
9564*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_advance_line:
9565*7304104dSAndroid Build Coastguard Worker 		  /* Takes one sleb128 parameter which is added to the
9566*7304104dSAndroid Build Coastguard Worker 		     line.  */
9567*7304104dSAndroid Build Coastguard Worker 		  if (lineendp - linep < 1)
9568*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9569*7304104dSAndroid Build Coastguard Worker 		  get_sleb128 (s128, linep, lineendp);
9570*7304104dSAndroid Build Coastguard Worker 		  line += s128;
9571*7304104dSAndroid Build Coastguard Worker 		  printf (_("\
9572*7304104dSAndroid Build Coastguard Worker  advance line by constant %d to %" PRId64 "\n"),
9573*7304104dSAndroid Build Coastguard Worker 			  s128, (int64_t) line);
9574*7304104dSAndroid Build Coastguard Worker 		  break;
9575*7304104dSAndroid Build Coastguard Worker 
9576*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_set_file:
9577*7304104dSAndroid Build Coastguard Worker 		  /* Takes one uleb128 parameter which is stored in file.  */
9578*7304104dSAndroid Build Coastguard Worker 		  if (lineendp - linep < 1)
9579*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9580*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (u128, linep, lineendp);
9581*7304104dSAndroid Build Coastguard Worker 		  printf (_(" set file to %" PRIu64 "\n"),
9582*7304104dSAndroid Build Coastguard Worker 			  (uint64_t) u128);
9583*7304104dSAndroid Build Coastguard Worker 		  break;
9584*7304104dSAndroid Build Coastguard Worker 
9585*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_set_column:
9586*7304104dSAndroid Build Coastguard Worker 		  /* Takes one uleb128 parameter which is stored in column.  */
9587*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (standard_opcode_lengths[opcode] != 1
9588*7304104dSAndroid Build Coastguard Worker 				|| lineendp - linep < 1))
9589*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9590*7304104dSAndroid Build Coastguard Worker 
9591*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (u128, linep, lineendp);
9592*7304104dSAndroid Build Coastguard Worker 		  printf (_(" set column to %" PRIu64 "\n"),
9593*7304104dSAndroid Build Coastguard Worker 			  (uint64_t) u128);
9594*7304104dSAndroid Build Coastguard Worker 		  break;
9595*7304104dSAndroid Build Coastguard Worker 
9596*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_negate_stmt:
9597*7304104dSAndroid Build Coastguard Worker 		  /* Takes no argument.  */
9598*7304104dSAndroid Build Coastguard Worker 		  is_stmt = 1 - is_stmt;
9599*7304104dSAndroid Build Coastguard Worker 		  printf (_(" set '%s' to %" PRIuFAST8 "\n"),
9600*7304104dSAndroid Build Coastguard Worker 			  "is_stmt", is_stmt);
9601*7304104dSAndroid Build Coastguard Worker 		  break;
9602*7304104dSAndroid Build Coastguard Worker 
9603*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_set_basic_block:
9604*7304104dSAndroid Build Coastguard Worker 		  /* Takes no argument.  */
9605*7304104dSAndroid Build Coastguard Worker 		  puts (_(" set basic block flag"));
9606*7304104dSAndroid Build Coastguard Worker 		  break;
9607*7304104dSAndroid Build Coastguard Worker 
9608*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_const_add_pc:
9609*7304104dSAndroid Build Coastguard Worker 		  /* Takes no argument.  */
9610*7304104dSAndroid Build Coastguard Worker 
9611*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (line_range == 0))
9612*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9613*7304104dSAndroid Build Coastguard Worker 
9614*7304104dSAndroid Build Coastguard Worker 		  advance_pc ((255 - opcode_base) / line_range);
9615*7304104dSAndroid Build Coastguard Worker 		  {
9616*7304104dSAndroid Build Coastguard Worker 		    printf (_(" advance address by constant %u to "),
9617*7304104dSAndroid Build Coastguard Worker 			    op_addr_advance);
9618*7304104dSAndroid Build Coastguard Worker 		    print_dwarf_addr (dwflmod, 0, address, address);
9619*7304104dSAndroid Build Coastguard Worker 		    if (op_index > 0)
9620*7304104dSAndroid Build Coastguard Worker 		      printf (_(", op_index to %u"), op_index);
9621*7304104dSAndroid Build Coastguard Worker 		    printf ("\n");
9622*7304104dSAndroid Build Coastguard Worker 		  }
9623*7304104dSAndroid Build Coastguard Worker 		  break;
9624*7304104dSAndroid Build Coastguard Worker 
9625*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_fixed_advance_pc:
9626*7304104dSAndroid Build Coastguard Worker 		  /* Takes one 16 bit parameter which is added to the
9627*7304104dSAndroid Build Coastguard Worker 		     address.  */
9628*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (standard_opcode_lengths[opcode] != 1
9629*7304104dSAndroid Build Coastguard Worker 				|| lineendp - linep < 2))
9630*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9631*7304104dSAndroid Build Coastguard Worker 
9632*7304104dSAndroid Build Coastguard Worker 		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
9633*7304104dSAndroid Build Coastguard Worker 		  address += u128;
9634*7304104dSAndroid Build Coastguard Worker 		  op_index = 0;
9635*7304104dSAndroid Build Coastguard Worker 		  {
9636*7304104dSAndroid Build Coastguard Worker 		    printf (_("\
9637*7304104dSAndroid Build Coastguard Worker  advance address by fixed value %u to \n"),
9638*7304104dSAndroid Build Coastguard Worker 			    u128);
9639*7304104dSAndroid Build Coastguard Worker 		    print_dwarf_addr (dwflmod, 0, address, address);
9640*7304104dSAndroid Build Coastguard Worker 		    printf ("\n");
9641*7304104dSAndroid Build Coastguard Worker 		  }
9642*7304104dSAndroid Build Coastguard Worker 		  break;
9643*7304104dSAndroid Build Coastguard Worker 
9644*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_set_prologue_end:
9645*7304104dSAndroid Build Coastguard Worker 		  /* Takes no argument.  */
9646*7304104dSAndroid Build Coastguard Worker 		  puts (_(" set prologue end flag"));
9647*7304104dSAndroid Build Coastguard Worker 		  break;
9648*7304104dSAndroid Build Coastguard Worker 
9649*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_set_epilogue_begin:
9650*7304104dSAndroid Build Coastguard Worker 		  /* Takes no argument.  */
9651*7304104dSAndroid Build Coastguard Worker 		  puts (_(" set epilogue begin flag"));
9652*7304104dSAndroid Build Coastguard Worker 		  break;
9653*7304104dSAndroid Build Coastguard Worker 
9654*7304104dSAndroid Build Coastguard Worker 		case DW_LNS_set_isa:
9655*7304104dSAndroid Build Coastguard Worker 		  /* Takes one uleb128 parameter which is stored in isa.  */
9656*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (standard_opcode_lengths[opcode] != 1
9657*7304104dSAndroid Build Coastguard Worker 				|| lineendp - linep < 1))
9658*7304104dSAndroid Build Coastguard Worker 		    goto invalid_unit;
9659*7304104dSAndroid Build Coastguard Worker 
9660*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (u128, linep, lineendp);
9661*7304104dSAndroid Build Coastguard Worker 		  printf (_(" set isa to %u\n"), u128);
9662*7304104dSAndroid Build Coastguard Worker 		  break;
9663*7304104dSAndroid Build Coastguard Worker 		}
9664*7304104dSAndroid Build Coastguard Worker 	    }
9665*7304104dSAndroid Build Coastguard Worker 	  else
9666*7304104dSAndroid Build Coastguard Worker 	    {
9667*7304104dSAndroid Build Coastguard Worker 	      /* This is a new opcode the generator but not we know about.
9668*7304104dSAndroid Build Coastguard Worker 		 Read the parameters associated with it but then discard
9669*7304104dSAndroid Build Coastguard Worker 		 everything.  Read all the parameters for this opcode.  */
9670*7304104dSAndroid Build Coastguard Worker 	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
9671*7304104dSAndroid Build Coastguard Worker 				" unknown opcode with %" PRIu8 " parameters:",
9672*7304104dSAndroid Build Coastguard Worker 				standard_opcode_lengths[opcode]),
9673*7304104dSAndroid Build Coastguard Worker 		      standard_opcode_lengths[opcode]);
9674*7304104dSAndroid Build Coastguard Worker 	      for (int n = standard_opcode_lengths[opcode];
9675*7304104dSAndroid Build Coastguard Worker 		   n > 0 && linep < lineendp; --n)
9676*7304104dSAndroid Build Coastguard Worker 		{
9677*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (u128, linep, lineendp);
9678*7304104dSAndroid Build Coastguard Worker 		  if (n != standard_opcode_lengths[opcode])
9679*7304104dSAndroid Build Coastguard Worker 		    putc_unlocked (',', stdout);
9680*7304104dSAndroid Build Coastguard Worker 		  printf (" %u", u128);
9681*7304104dSAndroid Build Coastguard Worker 		}
9682*7304104dSAndroid Build Coastguard Worker 
9683*7304104dSAndroid Build Coastguard Worker 	      /* Next round, ignore this opcode.  */
9684*7304104dSAndroid Build Coastguard Worker 	      continue;
9685*7304104dSAndroid Build Coastguard Worker 	    }
9686*7304104dSAndroid Build Coastguard Worker 	}
9687*7304104dSAndroid Build Coastguard Worker     }
9688*7304104dSAndroid Build Coastguard Worker 
9689*7304104dSAndroid Build Coastguard Worker   /* There must only be one data block.  */
9690*7304104dSAndroid Build Coastguard Worker   assert (elf_getdata (scn, data) == NULL);
9691*7304104dSAndroid Build Coastguard Worker }
9692*7304104dSAndroid Build Coastguard Worker 
9693*7304104dSAndroid Build Coastguard Worker 
9694*7304104dSAndroid Build Coastguard Worker static void
print_debug_loclists_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)9695*7304104dSAndroid Build Coastguard Worker print_debug_loclists_section (Dwfl_Module *dwflmod,
9696*7304104dSAndroid Build Coastguard Worker 			      Ebl *ebl,
9697*7304104dSAndroid Build Coastguard Worker 			      GElf_Ehdr *ehdr __attribute__ ((unused)),
9698*7304104dSAndroid Build Coastguard Worker 			      Elf_Scn *scn, GElf_Shdr *shdr,
9699*7304104dSAndroid Build Coastguard Worker 			      Dwarf *dbg)
9700*7304104dSAndroid Build Coastguard Worker {
9701*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loclists, scn);
9702*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
9703*7304104dSAndroid Build Coastguard Worker     return;
9704*7304104dSAndroid Build Coastguard Worker 
9705*7304104dSAndroid Build Coastguard Worker   printf (_("\
9706*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
9707*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
9708*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
9709*7304104dSAndroid Build Coastguard Worker 
9710*7304104dSAndroid Build Coastguard Worker   /* For the listptr to get the base address/CU.  */
9711*7304104dSAndroid Build Coastguard Worker   sort_listptr (&known_loclistsptr, "loclistsptr");
9712*7304104dSAndroid Build Coastguard Worker   size_t listptr_idx = 0;
9713*7304104dSAndroid Build Coastguard Worker 
9714*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = data->d_buf;
9715*7304104dSAndroid Build Coastguard Worker   const unsigned char *const dataend = ((unsigned char *) data->d_buf
9716*7304104dSAndroid Build Coastguard Worker 					+ data->d_size);
9717*7304104dSAndroid Build Coastguard Worker   while (readp < dataend)
9718*7304104dSAndroid Build Coastguard Worker     {
9719*7304104dSAndroid Build Coastguard Worker       if (unlikely (readp > dataend - 4))
9720*7304104dSAndroid Build Coastguard Worker 	{
9721*7304104dSAndroid Build Coastguard Worker 	invalid_data:
9722*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("invalid data in section [%zu] '%s'"),
9723*7304104dSAndroid Build Coastguard Worker 		 elf_ndxscn (scn), section_name (ebl, shdr));
9724*7304104dSAndroid Build Coastguard Worker 	  return;
9725*7304104dSAndroid Build Coastguard Worker 	}
9726*7304104dSAndroid Build Coastguard Worker 
9727*7304104dSAndroid Build Coastguard Worker       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
9728*7304104dSAndroid Build Coastguard Worker       printf (_("Table at Offset 0x%" PRIx64 ":\n\n"),
9729*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) offset);
9730*7304104dSAndroid Build Coastguard Worker 
9731*7304104dSAndroid Build Coastguard Worker       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
9732*7304104dSAndroid Build Coastguard Worker       unsigned int offset_size = 4;
9733*7304104dSAndroid Build Coastguard Worker       if (unlikely (unit_length == 0xffffffff))
9734*7304104dSAndroid Build Coastguard Worker 	{
9735*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (readp > dataend - 8))
9736*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
9737*7304104dSAndroid Build Coastguard Worker 
9738*7304104dSAndroid Build Coastguard Worker 	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
9739*7304104dSAndroid Build Coastguard Worker 	  offset_size = 8;
9740*7304104dSAndroid Build Coastguard Worker 	}
9741*7304104dSAndroid Build Coastguard Worker       printf (_(" Length:         %8" PRIu64 "\n"), unit_length);
9742*7304104dSAndroid Build Coastguard Worker 
9743*7304104dSAndroid Build Coastguard Worker       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
9744*7304104dSAndroid Build Coastguard Worker 	 bytes to complete the header.  And this unit cannot go beyond
9745*7304104dSAndroid Build Coastguard Worker 	 the section data.  */
9746*7304104dSAndroid Build Coastguard Worker       if (readp > dataend - 8
9747*7304104dSAndroid Build Coastguard Worker 	  || unit_length < 8
9748*7304104dSAndroid Build Coastguard Worker 	  || unit_length > (uint64_t) (dataend - readp))
9749*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
9750*7304104dSAndroid Build Coastguard Worker 
9751*7304104dSAndroid Build Coastguard Worker       const unsigned char *nexthdr = readp + unit_length;
9752*7304104dSAndroid Build Coastguard Worker 
9753*7304104dSAndroid Build Coastguard Worker       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
9754*7304104dSAndroid Build Coastguard Worker       printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
9755*7304104dSAndroid Build Coastguard Worker 
9756*7304104dSAndroid Build Coastguard Worker       if (version != 5)
9757*7304104dSAndroid Build Coastguard Worker 	{
9758*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("Unknown version"));
9759*7304104dSAndroid Build Coastguard Worker 	  goto next_table;
9760*7304104dSAndroid Build Coastguard Worker 	}
9761*7304104dSAndroid Build Coastguard Worker 
9762*7304104dSAndroid Build Coastguard Worker       uint8_t address_size = *readp++;
9763*7304104dSAndroid Build Coastguard Worker       printf (_(" Address size:   %8" PRIu64 "\n"),
9764*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) address_size);
9765*7304104dSAndroid Build Coastguard Worker 
9766*7304104dSAndroid Build Coastguard Worker       if (address_size != 4 && address_size != 8)
9767*7304104dSAndroid Build Coastguard Worker 	{
9768*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("unsupported address size"));
9769*7304104dSAndroid Build Coastguard Worker 	  goto next_table;
9770*7304104dSAndroid Build Coastguard Worker 	}
9771*7304104dSAndroid Build Coastguard Worker 
9772*7304104dSAndroid Build Coastguard Worker       uint8_t segment_size = *readp++;
9773*7304104dSAndroid Build Coastguard Worker       printf (_(" Segment size:   %8" PRIu64 "\n"),
9774*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) segment_size);
9775*7304104dSAndroid Build Coastguard Worker 
9776*7304104dSAndroid Build Coastguard Worker       if (segment_size != 0)
9777*7304104dSAndroid Build Coastguard Worker         {
9778*7304104dSAndroid Build Coastguard Worker           error (0, 0, _("unsupported segment size"));
9779*7304104dSAndroid Build Coastguard Worker           goto next_table;
9780*7304104dSAndroid Build Coastguard Worker         }
9781*7304104dSAndroid Build Coastguard Worker 
9782*7304104dSAndroid Build Coastguard Worker       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
9783*7304104dSAndroid Build Coastguard Worker       printf (_(" Offset entries: %8" PRIu64 "\n"),
9784*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) offset_entry_count);
9785*7304104dSAndroid Build Coastguard Worker 
9786*7304104dSAndroid Build Coastguard Worker       /* We need the CU that uses this unit to get the initial base address. */
9787*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr cu_base = 0;
9788*7304104dSAndroid Build Coastguard Worker       struct Dwarf_CU *cu = NULL;
9789*7304104dSAndroid Build Coastguard Worker       if (listptr_cu (&known_loclistsptr, &listptr_idx,
9790*7304104dSAndroid Build Coastguard Worker 		      (Dwarf_Off) offset,
9791*7304104dSAndroid Build Coastguard Worker 		      (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
9792*7304104dSAndroid Build Coastguard Worker 		      &cu_base, &cu)
9793*7304104dSAndroid Build Coastguard Worker 	  || split_dwarf_cu_base (dbg, &cu, &cu_base))
9794*7304104dSAndroid Build Coastguard Worker 	{
9795*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Die cudie;
9796*7304104dSAndroid Build Coastguard Worker 	  if (dwarf_cu_die (cu, &cudie,
9797*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL, NULL, NULL,
9798*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL) == NULL)
9799*7304104dSAndroid Build Coastguard Worker 	    printf (_(" Unknown CU base: "));
9800*7304104dSAndroid Build Coastguard Worker 	  else
9801*7304104dSAndroid Build Coastguard Worker 	    printf (_(" CU [%6" PRIx64 "] base: "),
9802*7304104dSAndroid Build Coastguard Worker 		    dwarf_dieoffset (&cudie));
9803*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
9804*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
9805*7304104dSAndroid Build Coastguard Worker 	}
9806*7304104dSAndroid Build Coastguard Worker       else
9807*7304104dSAndroid Build Coastguard Worker 	printf (_(" Not associated with a CU.\n"));
9808*7304104dSAndroid Build Coastguard Worker 
9809*7304104dSAndroid Build Coastguard Worker       printf ("\n");
9810*7304104dSAndroid Build Coastguard Worker 
9811*7304104dSAndroid Build Coastguard Worker       const unsigned char *offset_array_start = readp;
9812*7304104dSAndroid Build Coastguard Worker       if (offset_entry_count > 0)
9813*7304104dSAndroid Build Coastguard Worker 	{
9814*7304104dSAndroid Build Coastguard Worker 	  uint64_t max_entries = (unit_length - 8) / offset_size;
9815*7304104dSAndroid Build Coastguard Worker 	  if (offset_entry_count > max_entries)
9816*7304104dSAndroid Build Coastguard Worker 	    {
9817*7304104dSAndroid Build Coastguard Worker 	      error (0, 0,
9818*7304104dSAndroid Build Coastguard Worker 		     _("too many offset entries for unit length"));
9819*7304104dSAndroid Build Coastguard Worker 	      offset_entry_count = max_entries;
9820*7304104dSAndroid Build Coastguard Worker 	    }
9821*7304104dSAndroid Build Coastguard Worker 
9822*7304104dSAndroid Build Coastguard Worker 	  printf (_("  Offsets starting at 0x%" PRIx64 ":\n"),
9823*7304104dSAndroid Build Coastguard Worker 		  (uint64_t) (offset_array_start
9824*7304104dSAndroid Build Coastguard Worker 			      - (unsigned char *) data->d_buf));
9825*7304104dSAndroid Build Coastguard Worker 	  for (uint32_t idx = 0; idx < offset_entry_count; idx++)
9826*7304104dSAndroid Build Coastguard Worker 	    {
9827*7304104dSAndroid Build Coastguard Worker 	      printf ("   [%6" PRIu32 "] ", idx);
9828*7304104dSAndroid Build Coastguard Worker 	      if (offset_size == 4)
9829*7304104dSAndroid Build Coastguard Worker 		{
9830*7304104dSAndroid Build Coastguard Worker 		  uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
9831*7304104dSAndroid Build Coastguard Worker 		  printf ("0x%" PRIx32 "\n", off);
9832*7304104dSAndroid Build Coastguard Worker 		}
9833*7304104dSAndroid Build Coastguard Worker 	      else
9834*7304104dSAndroid Build Coastguard Worker 		{
9835*7304104dSAndroid Build Coastguard Worker 		  uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
9836*7304104dSAndroid Build Coastguard Worker 		  printf ("0x%" PRIx64 "\n", off);
9837*7304104dSAndroid Build Coastguard Worker 		}
9838*7304104dSAndroid Build Coastguard Worker 	    }
9839*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
9840*7304104dSAndroid Build Coastguard Worker 	}
9841*7304104dSAndroid Build Coastguard Worker 
9842*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr base = cu_base;
9843*7304104dSAndroid Build Coastguard Worker       bool start_of_list = true;
9844*7304104dSAndroid Build Coastguard Worker       while (readp < nexthdr)
9845*7304104dSAndroid Build Coastguard Worker 	{
9846*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off off = (Dwarf_Off) (readp - (unsigned char *) data->d_buf);
9847*7304104dSAndroid Build Coastguard Worker 	  if (listptr_attr (&known_loclistsptr, listptr_idx, off,
9848*7304104dSAndroid Build Coastguard Worker 			    DW_AT_GNU_locviews))
9849*7304104dSAndroid Build Coastguard Worker 	    {
9850*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Off next_off = next_listptr_offset (&known_loclistsptr,
9851*7304104dSAndroid Build Coastguard Worker 							&listptr_idx, off);
9852*7304104dSAndroid Build Coastguard Worker 	      const unsigned char *locp = readp;
9853*7304104dSAndroid Build Coastguard Worker 	      const unsigned char *locendp;
9854*7304104dSAndroid Build Coastguard Worker 	      if (next_off == 0
9855*7304104dSAndroid Build Coastguard Worker 		  || next_off > (size_t) (nexthdr - ((const unsigned char *)
9856*7304104dSAndroid Build Coastguard Worker 						     data->d_buf)))
9857*7304104dSAndroid Build Coastguard Worker 		locendp = nexthdr;
9858*7304104dSAndroid Build Coastguard Worker 	      else
9859*7304104dSAndroid Build Coastguard Worker 		locendp = (const unsigned char *) data->d_buf + next_off;
9860*7304104dSAndroid Build Coastguard Worker 
9861*7304104dSAndroid Build Coastguard Worker 	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
9862*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) (readp - (unsigned char *) data->d_buf),
9863*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) (readp - offset_array_start));
9864*7304104dSAndroid Build Coastguard Worker 
9865*7304104dSAndroid Build Coastguard Worker 	      while (locp < locendp)
9866*7304104dSAndroid Build Coastguard Worker 		{
9867*7304104dSAndroid Build Coastguard Worker 		  uint64_t v1, v2;
9868*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (v1, locp, locendp);
9869*7304104dSAndroid Build Coastguard Worker 		  if (locp >= locendp)
9870*7304104dSAndroid Build Coastguard Worker 		    {
9871*7304104dSAndroid Build Coastguard Worker 		      printf (_("    <INVALID DATA>\n"));
9872*7304104dSAndroid Build Coastguard Worker 		      break;
9873*7304104dSAndroid Build Coastguard Worker 		    }
9874*7304104dSAndroid Build Coastguard Worker 		  get_uleb128 (v2, locp, locendp);
9875*7304104dSAndroid Build Coastguard Worker 		  printf ("    view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
9876*7304104dSAndroid Build Coastguard Worker 		}
9877*7304104dSAndroid Build Coastguard Worker 
9878*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
9879*7304104dSAndroid Build Coastguard Worker 	      readp = (unsigned char *) locendp;
9880*7304104dSAndroid Build Coastguard Worker 	      continue;
9881*7304104dSAndroid Build Coastguard Worker 	    }
9882*7304104dSAndroid Build Coastguard Worker 
9883*7304104dSAndroid Build Coastguard Worker 	  uint8_t kind = *readp++;
9884*7304104dSAndroid Build Coastguard Worker 	  uint64_t op1, op2, len;
9885*7304104dSAndroid Build Coastguard Worker 
9886*7304104dSAndroid Build Coastguard Worker 	  /* Skip padding.  */
9887*7304104dSAndroid Build Coastguard Worker 	  if (start_of_list && kind == DW_LLE_end_of_list)
9888*7304104dSAndroid Build Coastguard Worker 	    continue;
9889*7304104dSAndroid Build Coastguard Worker 
9890*7304104dSAndroid Build Coastguard Worker 	  if (start_of_list)
9891*7304104dSAndroid Build Coastguard Worker 	    {
9892*7304104dSAndroid Build Coastguard Worker 	      base = cu_base;
9893*7304104dSAndroid Build Coastguard Worker 	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
9894*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
9895*7304104dSAndroid Build Coastguard Worker 		      (uint64_t) (readp - offset_array_start - 1));
9896*7304104dSAndroid Build Coastguard Worker 	      start_of_list = false;
9897*7304104dSAndroid Build Coastguard Worker 	    }
9898*7304104dSAndroid Build Coastguard Worker 
9899*7304104dSAndroid Build Coastguard Worker 	  printf ("    %s", dwarf_loc_list_encoding_name (kind));
9900*7304104dSAndroid Build Coastguard Worker 	  switch (kind)
9901*7304104dSAndroid Build Coastguard Worker 	    {
9902*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_end_of_list:
9903*7304104dSAndroid Build Coastguard Worker 	      start_of_list = true;
9904*7304104dSAndroid Build Coastguard Worker 	      printf ("\n\n");
9905*7304104dSAndroid Build Coastguard Worker 	      break;
9906*7304104dSAndroid Build Coastguard Worker 
9907*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_base_addressx:
9908*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
9909*7304104dSAndroid Build Coastguard Worker 		{
9910*7304104dSAndroid Build Coastguard Worker 		invalid_entry:
9911*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, _("invalid loclists data"));
9912*7304104dSAndroid Build Coastguard Worker 		  goto next_table;
9913*7304104dSAndroid Build Coastguard Worker 		}
9914*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
9915*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 "\n", op1);
9916*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
9917*7304104dSAndroid Build Coastguard Worker 		{
9918*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr;
9919*7304104dSAndroid Build Coastguard Worker 		  if (get_indexed_addr (cu, op1, &addr) != 0)
9920*7304104dSAndroid Build Coastguard Worker 		    printf ("      ???\n");
9921*7304104dSAndroid Build Coastguard Worker 		  else
9922*7304104dSAndroid Build Coastguard Worker 		    {
9923*7304104dSAndroid Build Coastguard Worker 		      printf ("      ");
9924*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size, addr, addr);
9925*7304104dSAndroid Build Coastguard Worker 		      printf ("\n");
9926*7304104dSAndroid Build Coastguard Worker 		    }
9927*7304104dSAndroid Build Coastguard Worker 		}
9928*7304104dSAndroid Build Coastguard Worker 	      break;
9929*7304104dSAndroid Build Coastguard Worker 
9930*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_startx_endx:
9931*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
9932*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
9933*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
9934*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
9935*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
9936*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
9937*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9938*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
9939*7304104dSAndroid Build Coastguard Worker 		{
9940*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr1;
9941*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr2;
9942*7304104dSAndroid Build Coastguard Worker 		  if (get_indexed_addr (cu, op1, &addr1) != 0
9943*7304104dSAndroid Build Coastguard Worker 		      || get_indexed_addr (cu, op2, &addr2) != 0)
9944*7304104dSAndroid Build Coastguard Worker 		    {
9945*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???..\n");
9946*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???\n");
9947*7304104dSAndroid Build Coastguard Worker 		    }
9948*7304104dSAndroid Build Coastguard Worker 		  else
9949*7304104dSAndroid Build Coastguard Worker 		    {
9950*7304104dSAndroid Build Coastguard Worker 		      printf ("      ");
9951*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9952*7304104dSAndroid Build Coastguard Worker 		      printf ("..\n      ");
9953*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size,
9954*7304104dSAndroid Build Coastguard Worker 					addr2 - 1, addr2);
9955*7304104dSAndroid Build Coastguard Worker 		      printf ("\n");
9956*7304104dSAndroid Build Coastguard Worker 		    }
9957*7304104dSAndroid Build Coastguard Worker 		}
9958*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
9959*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
9960*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (len, readp, nexthdr);
9961*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < len)
9962*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
9963*7304104dSAndroid Build Coastguard Worker 	      print_ops (dwflmod, dbg, 8, 8, version,
9964*7304104dSAndroid Build Coastguard Worker 			 address_size, offset_size, cu, len, readp);
9965*7304104dSAndroid Build Coastguard Worker 	      readp += len;
9966*7304104dSAndroid Build Coastguard Worker 	      break;
9967*7304104dSAndroid Build Coastguard Worker 
9968*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_startx_length:
9969*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
9970*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
9971*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
9972*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
9973*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
9974*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
9975*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
9976*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
9977*7304104dSAndroid Build Coastguard Worker 		{
9978*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr1;
9979*7304104dSAndroid Build Coastguard Worker 		  Dwarf_Addr addr2;
9980*7304104dSAndroid Build Coastguard Worker 		  if (get_indexed_addr (cu, op1, &addr1) != 0)
9981*7304104dSAndroid Build Coastguard Worker 		    {
9982*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???..\n");
9983*7304104dSAndroid Build Coastguard Worker 		      printf ("      ???\n");
9984*7304104dSAndroid Build Coastguard Worker 		    }
9985*7304104dSAndroid Build Coastguard Worker 		  else
9986*7304104dSAndroid Build Coastguard Worker 		    {
9987*7304104dSAndroid Build Coastguard Worker 		      addr2 = addr1 + op2;
9988*7304104dSAndroid Build Coastguard Worker 		      printf ("      ");
9989*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
9990*7304104dSAndroid Build Coastguard Worker 		      printf ("..\n      ");
9991*7304104dSAndroid Build Coastguard Worker 		      print_dwarf_addr (dwflmod, address_size,
9992*7304104dSAndroid Build Coastguard Worker 					addr2 - 1, addr2);
9993*7304104dSAndroid Build Coastguard Worker 		      printf ("\n");
9994*7304104dSAndroid Build Coastguard Worker 		    }
9995*7304104dSAndroid Build Coastguard Worker 		}
9996*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
9997*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
9998*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (len, readp, nexthdr);
9999*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < len)
10000*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10001*7304104dSAndroid Build Coastguard Worker 	      print_ops (dwflmod, dbg, 8, 8, version,
10002*7304104dSAndroid Build Coastguard Worker 			 address_size, offset_size, cu, len, readp);
10003*7304104dSAndroid Build Coastguard Worker 	      readp += len;
10004*7304104dSAndroid Build Coastguard Worker 	      break;
10005*7304104dSAndroid Build Coastguard Worker 
10006*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_offset_pair:
10007*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10008*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10009*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
10010*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10011*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10012*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
10013*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
10014*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
10015*7304104dSAndroid Build Coastguard Worker 		{
10016*7304104dSAndroid Build Coastguard Worker 		  op1 += base;
10017*7304104dSAndroid Build Coastguard Worker 		  op2 += base;
10018*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
10019*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op1, op1);
10020*7304104dSAndroid Build Coastguard Worker 		  printf ("..\n      ");
10021*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
10022*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
10023*7304104dSAndroid Build Coastguard Worker 		}
10024*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10025*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10026*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (len, readp, nexthdr);
10027*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < len)
10028*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10029*7304104dSAndroid Build Coastguard Worker 	      print_ops (dwflmod, dbg, 8, 8, version,
10030*7304104dSAndroid Build Coastguard Worker 			 address_size, offset_size, cu, len, readp);
10031*7304104dSAndroid Build Coastguard Worker 	      readp += len;
10032*7304104dSAndroid Build Coastguard Worker 	      break;
10033*7304104dSAndroid Build Coastguard Worker 
10034*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_default_location:
10035*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10036*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10037*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (len, readp, nexthdr);
10038*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < len)
10039*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10040*7304104dSAndroid Build Coastguard Worker 	      print_ops (dwflmod, dbg, 8, 8, version,
10041*7304104dSAndroid Build Coastguard Worker 			 address_size, offset_size, cu, len, readp);
10042*7304104dSAndroid Build Coastguard Worker 	      readp += len;
10043*7304104dSAndroid Build Coastguard Worker 	      break;
10044*7304104dSAndroid Build Coastguard Worker 
10045*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_base_address:
10046*7304104dSAndroid Build Coastguard Worker 	      if (address_size == 4)
10047*7304104dSAndroid Build Coastguard Worker 		{
10048*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 4)
10049*7304104dSAndroid Build Coastguard Worker 		    goto invalid_entry;
10050*7304104dSAndroid Build Coastguard Worker 		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
10051*7304104dSAndroid Build Coastguard Worker 		}
10052*7304104dSAndroid Build Coastguard Worker 	      else
10053*7304104dSAndroid Build Coastguard Worker 		{
10054*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 8)
10055*7304104dSAndroid Build Coastguard Worker 		    goto invalid_entry;
10056*7304104dSAndroid Build Coastguard Worker 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
10057*7304104dSAndroid Build Coastguard Worker 		}
10058*7304104dSAndroid Build Coastguard Worker 	      base = op1;
10059*7304104dSAndroid Build Coastguard Worker 	      printf (" 0x%" PRIx64 "\n", base);
10060*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
10061*7304104dSAndroid Build Coastguard Worker 		{
10062*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
10063*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, base, base);
10064*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
10065*7304104dSAndroid Build Coastguard Worker 		}
10066*7304104dSAndroid Build Coastguard Worker 	      break;
10067*7304104dSAndroid Build Coastguard Worker 
10068*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_start_end:
10069*7304104dSAndroid Build Coastguard Worker 	      if (address_size == 4)
10070*7304104dSAndroid Build Coastguard Worker 		{
10071*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 8)
10072*7304104dSAndroid Build Coastguard Worker 		    goto invalid_entry;
10073*7304104dSAndroid Build Coastguard Worker 		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
10074*7304104dSAndroid Build Coastguard Worker 		  op2 = read_4ubyte_unaligned_inc (dbg, readp);
10075*7304104dSAndroid Build Coastguard Worker 		}
10076*7304104dSAndroid Build Coastguard Worker 	      else
10077*7304104dSAndroid Build Coastguard Worker 		{
10078*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 16)
10079*7304104dSAndroid Build Coastguard Worker 		    goto invalid_entry;
10080*7304104dSAndroid Build Coastguard Worker 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
10081*7304104dSAndroid Build Coastguard Worker 		  op2 = read_8ubyte_unaligned_inc (dbg, readp);
10082*7304104dSAndroid Build Coastguard Worker 		}
10083*7304104dSAndroid Build Coastguard Worker 	      printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
10084*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
10085*7304104dSAndroid Build Coastguard Worker 		{
10086*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
10087*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op1, op1);
10088*7304104dSAndroid Build Coastguard Worker 		  printf ("..\n      ");
10089*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
10090*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
10091*7304104dSAndroid Build Coastguard Worker 		}
10092*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10093*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10094*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (len, readp, nexthdr);
10095*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < len)
10096*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10097*7304104dSAndroid Build Coastguard Worker 	      print_ops (dwflmod, dbg, 8, 8, version,
10098*7304104dSAndroid Build Coastguard Worker 			 address_size, offset_size, cu, len, readp);
10099*7304104dSAndroid Build Coastguard Worker 	      readp += len;
10100*7304104dSAndroid Build Coastguard Worker 	      break;
10101*7304104dSAndroid Build Coastguard Worker 
10102*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_start_length:
10103*7304104dSAndroid Build Coastguard Worker 	      if (address_size == 4)
10104*7304104dSAndroid Build Coastguard Worker 		{
10105*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 4)
10106*7304104dSAndroid Build Coastguard Worker 		    goto invalid_entry;
10107*7304104dSAndroid Build Coastguard Worker 		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
10108*7304104dSAndroid Build Coastguard Worker 		}
10109*7304104dSAndroid Build Coastguard Worker 	      else
10110*7304104dSAndroid Build Coastguard Worker 		{
10111*7304104dSAndroid Build Coastguard Worker 		  if ((uint64_t) (nexthdr - readp) < 8)
10112*7304104dSAndroid Build Coastguard Worker 		    goto invalid_entry;
10113*7304104dSAndroid Build Coastguard Worker 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
10114*7304104dSAndroid Build Coastguard Worker 		}
10115*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10116*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10117*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
10118*7304104dSAndroid Build Coastguard Worker 	      printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
10119*7304104dSAndroid Build Coastguard Worker 	      if (! print_unresolved_addresses)
10120*7304104dSAndroid Build Coastguard Worker 		{
10121*7304104dSAndroid Build Coastguard Worker 		  op2 = op1 + op2;
10122*7304104dSAndroid Build Coastguard Worker 		  printf ("      ");
10123*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op1, op1);
10124*7304104dSAndroid Build Coastguard Worker 		  printf ("..\n      ");
10125*7304104dSAndroid Build Coastguard Worker 		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
10126*7304104dSAndroid Build Coastguard Worker 		  printf ("\n");
10127*7304104dSAndroid Build Coastguard Worker 		}
10128*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10129*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10130*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (len, readp, nexthdr);
10131*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < len)
10132*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10133*7304104dSAndroid Build Coastguard Worker 	      print_ops (dwflmod, dbg, 8, 8, version,
10134*7304104dSAndroid Build Coastguard Worker 			 address_size, offset_size, cu, len, readp);
10135*7304104dSAndroid Build Coastguard Worker 	      readp += len;
10136*7304104dSAndroid Build Coastguard Worker 	      break;
10137*7304104dSAndroid Build Coastguard Worker 
10138*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_GNU_view_pair:
10139*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10140*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10141*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op1, readp, nexthdr);
10142*7304104dSAndroid Build Coastguard Worker 	      if ((uint64_t) (nexthdr - readp) < 1)
10143*7304104dSAndroid Build Coastguard Worker 		goto invalid_entry;
10144*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (op2, readp, nexthdr);
10145*7304104dSAndroid Build Coastguard Worker 	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
10146*7304104dSAndroid Build Coastguard Worker 	      break;
10147*7304104dSAndroid Build Coastguard Worker 
10148*7304104dSAndroid Build Coastguard Worker 	    default:
10149*7304104dSAndroid Build Coastguard Worker 	      goto invalid_entry;
10150*7304104dSAndroid Build Coastguard Worker 	    }
10151*7304104dSAndroid Build Coastguard Worker 	}
10152*7304104dSAndroid Build Coastguard Worker 
10153*7304104dSAndroid Build Coastguard Worker     next_table:
10154*7304104dSAndroid Build Coastguard Worker       if (readp != nexthdr)
10155*7304104dSAndroid Build Coastguard Worker 	{
10156*7304104dSAndroid Build Coastguard Worker           size_t padding = nexthdr - readp;
10157*7304104dSAndroid Build Coastguard Worker           printf (_("   %zu padding bytes\n\n"), padding);
10158*7304104dSAndroid Build Coastguard Worker 	  readp = nexthdr;
10159*7304104dSAndroid Build Coastguard Worker 	}
10160*7304104dSAndroid Build Coastguard Worker     }
10161*7304104dSAndroid Build Coastguard Worker }
10162*7304104dSAndroid Build Coastguard Worker 
10163*7304104dSAndroid Build Coastguard Worker 
10164*7304104dSAndroid Build Coastguard Worker static void
print_debug_loc_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)10165*7304104dSAndroid Build Coastguard Worker print_debug_loc_section (Dwfl_Module *dwflmod,
10166*7304104dSAndroid Build Coastguard Worker 			 Ebl *ebl, GElf_Ehdr *ehdr,
10167*7304104dSAndroid Build Coastguard Worker 			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10168*7304104dSAndroid Build Coastguard Worker {
10169*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loc, scn);
10170*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
10171*7304104dSAndroid Build Coastguard Worker     return;
10172*7304104dSAndroid Build Coastguard Worker 
10173*7304104dSAndroid Build Coastguard Worker   printf (_("\
10174*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10175*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
10176*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
10177*7304104dSAndroid Build Coastguard Worker 
10178*7304104dSAndroid Build Coastguard Worker   sort_listptr (&known_locsptr, "loclistptr");
10179*7304104dSAndroid Build Coastguard Worker   size_t listptr_idx = 0;
10180*7304104dSAndroid Build Coastguard Worker 
10181*7304104dSAndroid Build Coastguard Worker   uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
10182*7304104dSAndroid Build Coastguard Worker   uint_fast8_t offset_size = 4;
10183*7304104dSAndroid Build Coastguard Worker 
10184*7304104dSAndroid Build Coastguard Worker   bool first = true;
10185*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr base = 0;
10186*7304104dSAndroid Build Coastguard Worker   unsigned char *readp = data->d_buf;
10187*7304104dSAndroid Build Coastguard Worker   unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
10188*7304104dSAndroid Build Coastguard Worker   Dwarf_CU *last_cu = NULL;
10189*7304104dSAndroid Build Coastguard Worker   while (readp < endp)
10190*7304104dSAndroid Build Coastguard Worker     {
10191*7304104dSAndroid Build Coastguard Worker       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
10192*7304104dSAndroid Build Coastguard Worker       Dwarf_CU *cu = last_cu;
10193*7304104dSAndroid Build Coastguard Worker       unsigned int attr = 0;
10194*7304104dSAndroid Build Coastguard Worker 
10195*7304104dSAndroid Build Coastguard Worker       if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
10196*7304104dSAndroid Build Coastguard Worker 				      &address_size, &offset_size, &base,
10197*7304104dSAndroid Build Coastguard Worker 				      &cu, offset, &readp, endp, &attr))
10198*7304104dSAndroid Build Coastguard Worker 	continue;
10199*7304104dSAndroid Build Coastguard Worker 
10200*7304104dSAndroid Build Coastguard Worker       if (last_cu != cu)
10201*7304104dSAndroid Build Coastguard Worker        {
10202*7304104dSAndroid Build Coastguard Worker 	Dwarf_Die cudie;
10203*7304104dSAndroid Build Coastguard Worker 	if (dwarf_cu_die (cu, &cudie,
10204*7304104dSAndroid Build Coastguard Worker 			  NULL, NULL, NULL, NULL,
10205*7304104dSAndroid Build Coastguard Worker 			  NULL, NULL) == NULL)
10206*7304104dSAndroid Build Coastguard Worker 	  printf (_("\n Unknown CU base: "));
10207*7304104dSAndroid Build Coastguard Worker 	else
10208*7304104dSAndroid Build Coastguard Worker 	  printf (_("\n CU [%6" PRIx64 "] base: "),
10209*7304104dSAndroid Build Coastguard Worker 		  dwarf_dieoffset (&cudie));
10210*7304104dSAndroid Build Coastguard Worker 	print_dwarf_addr (dwflmod, address_size, base, base);
10211*7304104dSAndroid Build Coastguard Worker 	printf ("\n");
10212*7304104dSAndroid Build Coastguard Worker        }
10213*7304104dSAndroid Build Coastguard Worker       last_cu = cu;
10214*7304104dSAndroid Build Coastguard Worker 
10215*7304104dSAndroid Build Coastguard Worker       if (attr == DW_AT_GNU_locviews)
10216*7304104dSAndroid Build Coastguard Worker 	{
10217*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
10218*7304104dSAndroid Build Coastguard Worker 						    &listptr_idx, offset);
10219*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *locp = readp;
10220*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *locendp;
10221*7304104dSAndroid Build Coastguard Worker 	  if (next_off == 0
10222*7304104dSAndroid Build Coastguard Worker 	      || next_off > (size_t) (endp
10223*7304104dSAndroid Build Coastguard Worker 				      - (const unsigned char *) data->d_buf))
10224*7304104dSAndroid Build Coastguard Worker 	    locendp = endp;
10225*7304104dSAndroid Build Coastguard Worker 	  else
10226*7304104dSAndroid Build Coastguard Worker 	    locendp = (const unsigned char *) data->d_buf + next_off;
10227*7304104dSAndroid Build Coastguard Worker 
10228*7304104dSAndroid Build Coastguard Worker 	  while (locp < locendp)
10229*7304104dSAndroid Build Coastguard Worker 	    {
10230*7304104dSAndroid Build Coastguard Worker 	      uint64_t v1, v2;
10231*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (v1, locp, locendp);
10232*7304104dSAndroid Build Coastguard Worker 	      if (locp >= locendp)
10233*7304104dSAndroid Build Coastguard Worker 		{
10234*7304104dSAndroid Build Coastguard Worker 		  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
10235*7304104dSAndroid Build Coastguard Worker 		  break;
10236*7304104dSAndroid Build Coastguard Worker 		}
10237*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (v2, locp, locendp);
10238*7304104dSAndroid Build Coastguard Worker 	      if (first)		/* First view pair in a list.  */
10239*7304104dSAndroid Build Coastguard Worker 		printf (" [%6tx] ", offset);
10240*7304104dSAndroid Build Coastguard Worker 	      else
10241*7304104dSAndroid Build Coastguard Worker 		printf ("          ");
10242*7304104dSAndroid Build Coastguard Worker 	      printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
10243*7304104dSAndroid Build Coastguard Worker 	      first = false;
10244*7304104dSAndroid Build Coastguard Worker 	    }
10245*7304104dSAndroid Build Coastguard Worker 
10246*7304104dSAndroid Build Coastguard Worker 	  first = true;
10247*7304104dSAndroid Build Coastguard Worker 	  readp = (unsigned char *) locendp;
10248*7304104dSAndroid Build Coastguard Worker 	  continue;
10249*7304104dSAndroid Build Coastguard Worker 	}
10250*7304104dSAndroid Build Coastguard Worker 
10251*7304104dSAndroid Build Coastguard Worker       /* GNU DebugFission encoded addresses as addrx.  */
10252*7304104dSAndroid Build Coastguard Worker       bool is_debugfission = ((cu != NULL
10253*7304104dSAndroid Build Coastguard Worker 			       || split_dwarf_cu_base (dbg, &cu, &base))
10254*7304104dSAndroid Build Coastguard Worker 			      && (cu->version < 5
10255*7304104dSAndroid Build Coastguard Worker 				  && cu->unit_type == DW_UT_split_compile));
10256*7304104dSAndroid Build Coastguard Worker       if (!is_debugfission
10257*7304104dSAndroid Build Coastguard Worker 	  && unlikely (data->d_size - offset < (size_t) address_size * 2))
10258*7304104dSAndroid Build Coastguard Worker         {
10259*7304104dSAndroid Build Coastguard Worker 	invalid_data:
10260*7304104dSAndroid Build Coastguard Worker 	  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
10261*7304104dSAndroid Build Coastguard Worker 	  break;
10262*7304104dSAndroid Build Coastguard Worker 	}
10263*7304104dSAndroid Build Coastguard Worker 
10264*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr begin;
10265*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr end;
10266*7304104dSAndroid Build Coastguard Worker       bool use_base = true;
10267*7304104dSAndroid Build Coastguard Worker       if (is_debugfission)
10268*7304104dSAndroid Build Coastguard Worker 	{
10269*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *locp = readp;
10270*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *locendp = readp + data->d_size;
10271*7304104dSAndroid Build Coastguard Worker 	  if (locp >= locendp)
10272*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
10273*7304104dSAndroid Build Coastguard Worker 
10274*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word idx;
10275*7304104dSAndroid Build Coastguard Worker 	  unsigned char code = *locp++;
10276*7304104dSAndroid Build Coastguard Worker 	  switch (code)
10277*7304104dSAndroid Build Coastguard Worker 	    {
10278*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_GNU_end_of_list_entry:
10279*7304104dSAndroid Build Coastguard Worker 	      begin = 0;
10280*7304104dSAndroid Build Coastguard Worker 	      end = 0;
10281*7304104dSAndroid Build Coastguard Worker 	      break;
10282*7304104dSAndroid Build Coastguard Worker 
10283*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_GNU_base_address_selection_entry:
10284*7304104dSAndroid Build Coastguard Worker 	      if (locp >= locendp)
10285*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10286*7304104dSAndroid Build Coastguard Worker 	      begin = (Dwarf_Addr) -1;
10287*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (idx, locp, locendp);
10288*7304104dSAndroid Build Coastguard Worker 	      if (get_indexed_addr (cu, idx, &end) != 0)
10289*7304104dSAndroid Build Coastguard Worker 		end = idx; /* ... */
10290*7304104dSAndroid Build Coastguard Worker 	      break;
10291*7304104dSAndroid Build Coastguard Worker 
10292*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_GNU_start_end_entry:
10293*7304104dSAndroid Build Coastguard Worker 	      if (locp >= locendp)
10294*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10295*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (idx, locp, locendp);
10296*7304104dSAndroid Build Coastguard Worker 	      if (get_indexed_addr (cu, idx, &begin) != 0)
10297*7304104dSAndroid Build Coastguard Worker 		begin = idx; /* ... */
10298*7304104dSAndroid Build Coastguard Worker 	      if (locp >= locendp)
10299*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10300*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (idx, locp, locendp);
10301*7304104dSAndroid Build Coastguard Worker 	      if (get_indexed_addr (cu, idx, &end) != 0)
10302*7304104dSAndroid Build Coastguard Worker 		end = idx; /* ... */
10303*7304104dSAndroid Build Coastguard Worker 	      use_base = false;
10304*7304104dSAndroid Build Coastguard Worker 	      break;
10305*7304104dSAndroid Build Coastguard Worker 
10306*7304104dSAndroid Build Coastguard Worker 	    case DW_LLE_GNU_start_length_entry:
10307*7304104dSAndroid Build Coastguard Worker 	      if (locp >= locendp)
10308*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10309*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (idx, locp, locendp);
10310*7304104dSAndroid Build Coastguard Worker 	      if (get_indexed_addr (cu, idx, &begin) != 0)
10311*7304104dSAndroid Build Coastguard Worker 		begin = idx; /* ... */
10312*7304104dSAndroid Build Coastguard Worker 	      if (locendp - locp < 4)
10313*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10314*7304104dSAndroid Build Coastguard Worker 	      end = read_4ubyte_unaligned_inc (dbg, locp);
10315*7304104dSAndroid Build Coastguard Worker 	      end += begin;
10316*7304104dSAndroid Build Coastguard Worker 	      use_base = false;
10317*7304104dSAndroid Build Coastguard Worker 	      break;
10318*7304104dSAndroid Build Coastguard Worker 
10319*7304104dSAndroid Build Coastguard Worker 	    default:
10320*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10321*7304104dSAndroid Build Coastguard Worker 	    }
10322*7304104dSAndroid Build Coastguard Worker 
10323*7304104dSAndroid Build Coastguard Worker 	  readp = (unsigned char *) locp;
10324*7304104dSAndroid Build Coastguard Worker 	}
10325*7304104dSAndroid Build Coastguard Worker       else if (address_size == 8)
10326*7304104dSAndroid Build Coastguard Worker 	{
10327*7304104dSAndroid Build Coastguard Worker 	  begin = read_8ubyte_unaligned_inc (dbg, readp);
10328*7304104dSAndroid Build Coastguard Worker 	  end = read_8ubyte_unaligned_inc (dbg, readp);
10329*7304104dSAndroid Build Coastguard Worker 	}
10330*7304104dSAndroid Build Coastguard Worker       else
10331*7304104dSAndroid Build Coastguard Worker 	{
10332*7304104dSAndroid Build Coastguard Worker 	  begin = read_4ubyte_unaligned_inc (dbg, readp);
10333*7304104dSAndroid Build Coastguard Worker 	  end = read_4ubyte_unaligned_inc (dbg, readp);
10334*7304104dSAndroid Build Coastguard Worker 	  if (begin == (Dwarf_Addr) (uint32_t) -1)
10335*7304104dSAndroid Build Coastguard Worker 	    begin = (Dwarf_Addr) -1l;
10336*7304104dSAndroid Build Coastguard Worker 	}
10337*7304104dSAndroid Build Coastguard Worker 
10338*7304104dSAndroid Build Coastguard Worker       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
10339*7304104dSAndroid Build Coastguard Worker 	{
10340*7304104dSAndroid Build Coastguard Worker 	  if (first)
10341*7304104dSAndroid Build Coastguard Worker 	    printf (" [%6tx] ", offset);
10342*7304104dSAndroid Build Coastguard Worker 	  else
10343*7304104dSAndroid Build Coastguard Worker 	    printf ("          ");
10344*7304104dSAndroid Build Coastguard Worker 	  puts (_("base address"));
10345*7304104dSAndroid Build Coastguard Worker 	  printf ("          ");
10346*7304104dSAndroid Build Coastguard Worker 	  print_dwarf_addr (dwflmod, address_size, end, end);
10347*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
10348*7304104dSAndroid Build Coastguard Worker 	  base = end;
10349*7304104dSAndroid Build Coastguard Worker 	  first = false;
10350*7304104dSAndroid Build Coastguard Worker 	}
10351*7304104dSAndroid Build Coastguard Worker       else if (begin == 0 && end == 0) /* End of list entry.  */
10352*7304104dSAndroid Build Coastguard Worker 	{
10353*7304104dSAndroid Build Coastguard Worker 	  if (first)
10354*7304104dSAndroid Build Coastguard Worker 	    printf (_(" [%6tx] empty list\n"), offset);
10355*7304104dSAndroid Build Coastguard Worker 	  first = true;
10356*7304104dSAndroid Build Coastguard Worker 	}
10357*7304104dSAndroid Build Coastguard Worker       else
10358*7304104dSAndroid Build Coastguard Worker 	{
10359*7304104dSAndroid Build Coastguard Worker 	  /* We have a location expression entry.  */
10360*7304104dSAndroid Build Coastguard Worker 	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
10361*7304104dSAndroid Build Coastguard Worker 
10362*7304104dSAndroid Build Coastguard Worker 	  if (first)		/* First entry in a list.  */
10363*7304104dSAndroid Build Coastguard Worker 	    printf (" [%6tx] ", offset);
10364*7304104dSAndroid Build Coastguard Worker 	  else
10365*7304104dSAndroid Build Coastguard Worker 	    printf ("          ");
10366*7304104dSAndroid Build Coastguard Worker 
10367*7304104dSAndroid Build Coastguard Worker 	  printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
10368*7304104dSAndroid Build Coastguard Worker 	  if (! print_unresolved_addresses)
10369*7304104dSAndroid Build Coastguard Worker 	    {
10370*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Addr dab = use_base ? base + begin : begin;
10371*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Addr dae = use_base ? base + end : end;
10372*7304104dSAndroid Build Coastguard Worker 	      printf ("          ");
10373*7304104dSAndroid Build Coastguard Worker 	      print_dwarf_addr (dwflmod, address_size, dab, dab);
10374*7304104dSAndroid Build Coastguard Worker 	      printf ("..\n          ");
10375*7304104dSAndroid Build Coastguard Worker 	      print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
10376*7304104dSAndroid Build Coastguard Worker 	      printf ("\n");
10377*7304104dSAndroid Build Coastguard Worker 	    }
10378*7304104dSAndroid Build Coastguard Worker 
10379*7304104dSAndroid Build Coastguard Worker 	  if (endp - readp <= (ptrdiff_t) len)
10380*7304104dSAndroid Build Coastguard Worker 	    {
10381*7304104dSAndroid Build Coastguard Worker 	      fputs (_("   <INVALID DATA>\n"), stdout);
10382*7304104dSAndroid Build Coastguard Worker 	      break;
10383*7304104dSAndroid Build Coastguard Worker 	    }
10384*7304104dSAndroid Build Coastguard Worker 
10385*7304104dSAndroid Build Coastguard Worker 	  print_ops (dwflmod, dbg, 11, 11,
10386*7304104dSAndroid Build Coastguard Worker 		     cu != NULL ? cu->version : 3,
10387*7304104dSAndroid Build Coastguard Worker 		     address_size, offset_size, cu, len, readp);
10388*7304104dSAndroid Build Coastguard Worker 
10389*7304104dSAndroid Build Coastguard Worker 	  first = false;
10390*7304104dSAndroid Build Coastguard Worker 	  readp += len;
10391*7304104dSAndroid Build Coastguard Worker 	}
10392*7304104dSAndroid Build Coastguard Worker     }
10393*7304104dSAndroid Build Coastguard Worker }
10394*7304104dSAndroid Build Coastguard Worker 
10395*7304104dSAndroid Build Coastguard Worker struct mac_culist
10396*7304104dSAndroid Build Coastguard Worker {
10397*7304104dSAndroid Build Coastguard Worker   Dwarf_Die die;
10398*7304104dSAndroid Build Coastguard Worker   Dwarf_Off offset;
10399*7304104dSAndroid Build Coastguard Worker   Dwarf_Files *files;
10400*7304104dSAndroid Build Coastguard Worker   struct mac_culist *next;
10401*7304104dSAndroid Build Coastguard Worker };
10402*7304104dSAndroid Build Coastguard Worker 
10403*7304104dSAndroid Build Coastguard Worker 
10404*7304104dSAndroid Build Coastguard Worker static int
mac_compare(const void * p1,const void * p2)10405*7304104dSAndroid Build Coastguard Worker mac_compare (const void *p1, const void *p2)
10406*7304104dSAndroid Build Coastguard Worker {
10407*7304104dSAndroid Build Coastguard Worker   struct mac_culist *m1 = (struct mac_culist *) p1;
10408*7304104dSAndroid Build Coastguard Worker   struct mac_culist *m2 = (struct mac_culist *) p2;
10409*7304104dSAndroid Build Coastguard Worker 
10410*7304104dSAndroid Build Coastguard Worker   if (m1->offset < m2->offset)
10411*7304104dSAndroid Build Coastguard Worker     return -1;
10412*7304104dSAndroid Build Coastguard Worker   if (m1->offset > m2->offset)
10413*7304104dSAndroid Build Coastguard Worker     return 1;
10414*7304104dSAndroid Build Coastguard Worker   return 0;
10415*7304104dSAndroid Build Coastguard Worker }
10416*7304104dSAndroid Build Coastguard Worker 
10417*7304104dSAndroid Build Coastguard Worker 
10418*7304104dSAndroid Build Coastguard Worker static void
print_debug_macinfo_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)10419*7304104dSAndroid Build Coastguard Worker print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10420*7304104dSAndroid Build Coastguard Worker 			     Ebl *ebl,
10421*7304104dSAndroid Build Coastguard Worker 			     GElf_Ehdr *ehdr __attribute__ ((unused)),
10422*7304104dSAndroid Build Coastguard Worker 			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10423*7304104dSAndroid Build Coastguard Worker {
10424*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macinfo, scn);
10425*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
10426*7304104dSAndroid Build Coastguard Worker     return;
10427*7304104dSAndroid Build Coastguard Worker 
10428*7304104dSAndroid Build Coastguard Worker   printf (_("\
10429*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10430*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
10431*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
10432*7304104dSAndroid Build Coastguard Worker   putc_unlocked ('\n', stdout);
10433*7304104dSAndroid Build Coastguard Worker 
10434*7304104dSAndroid Build Coastguard Worker   /* There is no function in libdw to iterate over the raw content of
10435*7304104dSAndroid Build Coastguard Worker      the section but it is easy enough to do.  */
10436*7304104dSAndroid Build Coastguard Worker 
10437*7304104dSAndroid Build Coastguard Worker   /* Get the source file information for all CUs.  */
10438*7304104dSAndroid Build Coastguard Worker   Dwarf_Off offset;
10439*7304104dSAndroid Build Coastguard Worker   Dwarf_Off ncu = 0;
10440*7304104dSAndroid Build Coastguard Worker   size_t hsize;
10441*7304104dSAndroid Build Coastguard Worker   struct mac_culist *culist = NULL;
10442*7304104dSAndroid Build Coastguard Worker   size_t nculist = 0;
10443*7304104dSAndroid Build Coastguard Worker   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
10444*7304104dSAndroid Build Coastguard Worker     {
10445*7304104dSAndroid Build Coastguard Worker       Dwarf_Die cudie;
10446*7304104dSAndroid Build Coastguard Worker       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
10447*7304104dSAndroid Build Coastguard Worker 	continue;
10448*7304104dSAndroid Build Coastguard Worker 
10449*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute attr;
10450*7304104dSAndroid Build Coastguard Worker       if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
10451*7304104dSAndroid Build Coastguard Worker 	continue;
10452*7304104dSAndroid Build Coastguard Worker 
10453*7304104dSAndroid Build Coastguard Worker       Dwarf_Word macoff;
10454*7304104dSAndroid Build Coastguard Worker       if (dwarf_formudata (&attr, &macoff) != 0)
10455*7304104dSAndroid Build Coastguard Worker 	continue;
10456*7304104dSAndroid Build Coastguard Worker 
10457*7304104dSAndroid Build Coastguard Worker       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
10458*7304104dSAndroid Build Coastguard Worker       newp->die = cudie;
10459*7304104dSAndroid Build Coastguard Worker       newp->offset = macoff;
10460*7304104dSAndroid Build Coastguard Worker       newp->files = NULL;
10461*7304104dSAndroid Build Coastguard Worker       newp->next = culist;
10462*7304104dSAndroid Build Coastguard Worker       culist = newp;
10463*7304104dSAndroid Build Coastguard Worker       ++nculist;
10464*7304104dSAndroid Build Coastguard Worker     }
10465*7304104dSAndroid Build Coastguard Worker 
10466*7304104dSAndroid Build Coastguard Worker   /* Convert the list into an array for easier consumption.  */
10467*7304104dSAndroid Build Coastguard Worker   struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
10468*7304104dSAndroid Build Coastguard Worker 							 * sizeof (*cus));
10469*7304104dSAndroid Build Coastguard Worker   /* Add sentinel.  */
10470*7304104dSAndroid Build Coastguard Worker   cus[nculist].offset = data->d_size;
10471*7304104dSAndroid Build Coastguard Worker   cus[nculist].files = (Dwarf_Files *) -1l;
10472*7304104dSAndroid Build Coastguard Worker   if (nculist > 0)
10473*7304104dSAndroid Build Coastguard Worker     {
10474*7304104dSAndroid Build Coastguard Worker       for (size_t cnt = nculist - 1; culist != NULL; --cnt)
10475*7304104dSAndroid Build Coastguard Worker 	{
10476*7304104dSAndroid Build Coastguard Worker 	  assert (cnt < nculist);
10477*7304104dSAndroid Build Coastguard Worker 	  cus[cnt] = *culist;
10478*7304104dSAndroid Build Coastguard Worker 	  culist = culist->next;
10479*7304104dSAndroid Build Coastguard Worker 	}
10480*7304104dSAndroid Build Coastguard Worker 
10481*7304104dSAndroid Build Coastguard Worker       /* Sort the array according to the offset in the .debug_macinfo
10482*7304104dSAndroid Build Coastguard Worker 	 section.  Note we keep the sentinel at the end.  */
10483*7304104dSAndroid Build Coastguard Worker       qsort (cus, nculist, sizeof (*cus), mac_compare);
10484*7304104dSAndroid Build Coastguard Worker     }
10485*7304104dSAndroid Build Coastguard Worker 
10486*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = (const unsigned char *) data->d_buf;
10487*7304104dSAndroid Build Coastguard Worker   const unsigned char *readendp = readp + data->d_size;
10488*7304104dSAndroid Build Coastguard Worker   int level = 1;
10489*7304104dSAndroid Build Coastguard Worker 
10490*7304104dSAndroid Build Coastguard Worker   while (readp < readendp)
10491*7304104dSAndroid Build Coastguard Worker     {
10492*7304104dSAndroid Build Coastguard Worker       unsigned int opcode = *readp++;
10493*7304104dSAndroid Build Coastguard Worker       unsigned int u128;
10494*7304104dSAndroid Build Coastguard Worker       unsigned int u128_2;
10495*7304104dSAndroid Build Coastguard Worker       const unsigned char *endp;
10496*7304104dSAndroid Build Coastguard Worker 
10497*7304104dSAndroid Build Coastguard Worker       switch (opcode)
10498*7304104dSAndroid Build Coastguard Worker 	{
10499*7304104dSAndroid Build Coastguard Worker 	case DW_MACINFO_define:
10500*7304104dSAndroid Build Coastguard Worker 	case DW_MACINFO_undef:
10501*7304104dSAndroid Build Coastguard Worker 	case DW_MACINFO_vendor_ext:
10502*7304104dSAndroid Build Coastguard Worker 	  /*  For the first two opcodes the parameters are
10503*7304104dSAndroid Build Coastguard Worker 		line, string
10504*7304104dSAndroid Build Coastguard Worker 	      For the latter
10505*7304104dSAndroid Build Coastguard Worker 		number, string.
10506*7304104dSAndroid Build Coastguard Worker 	      We can treat these cases together.  */
10507*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (u128, readp, readendp);
10508*7304104dSAndroid Build Coastguard Worker 
10509*7304104dSAndroid Build Coastguard Worker 	  endp = memchr (readp, '\0', readendp - readp);
10510*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (endp == NULL))
10511*7304104dSAndroid Build Coastguard Worker 	    {
10512*7304104dSAndroid Build Coastguard Worker 	      printf (_("\
10513*7304104dSAndroid Build Coastguard Worker %*s*** non-terminated string at end of section"),
10514*7304104dSAndroid Build Coastguard Worker 		      level, "");
10515*7304104dSAndroid Build Coastguard Worker 	      return;
10516*7304104dSAndroid Build Coastguard Worker 	    }
10517*7304104dSAndroid Build Coastguard Worker 
10518*7304104dSAndroid Build Coastguard Worker 	  if (opcode == DW_MACINFO_define)
10519*7304104dSAndroid Build Coastguard Worker 	    printf ("%*s#define %s, line %u\n",
10520*7304104dSAndroid Build Coastguard Worker 		    level, "", (char *) readp, u128);
10521*7304104dSAndroid Build Coastguard Worker 	  else if (opcode == DW_MACINFO_undef)
10522*7304104dSAndroid Build Coastguard Worker 	    printf ("%*s#undef %s, line %u\n",
10523*7304104dSAndroid Build Coastguard Worker 		    level, "", (char *) readp, u128);
10524*7304104dSAndroid Build Coastguard Worker 	  else
10525*7304104dSAndroid Build Coastguard Worker 	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
10526*7304104dSAndroid Build Coastguard Worker 
10527*7304104dSAndroid Build Coastguard Worker 	  readp = endp + 1;
10528*7304104dSAndroid Build Coastguard Worker 	  break;
10529*7304104dSAndroid Build Coastguard Worker 
10530*7304104dSAndroid Build Coastguard Worker 	case DW_MACINFO_start_file:
10531*7304104dSAndroid Build Coastguard Worker 	  /* The two parameters are line and file index, in this order.  */
10532*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (u128, readp, readendp);
10533*7304104dSAndroid Build Coastguard Worker 	  if (readendp - readp < 1)
10534*7304104dSAndroid Build Coastguard Worker 	    {
10535*7304104dSAndroid Build Coastguard Worker 	      printf (_("\
10536*7304104dSAndroid Build Coastguard Worker %*s*** missing DW_MACINFO_start_file argument at end of section"),
10537*7304104dSAndroid Build Coastguard Worker 		      level, "");
10538*7304104dSAndroid Build Coastguard Worker 	      return;
10539*7304104dSAndroid Build Coastguard Worker 	    }
10540*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (u128_2, readp, readendp);
10541*7304104dSAndroid Build Coastguard Worker 
10542*7304104dSAndroid Build Coastguard Worker 	  /* Find the CU DIE for this file.  */
10543*7304104dSAndroid Build Coastguard Worker 	  size_t macoff = readp - (const unsigned char *) data->d_buf;
10544*7304104dSAndroid Build Coastguard Worker 	  const char *fname = "???";
10545*7304104dSAndroid Build Coastguard Worker 	  if (macoff >= cus[0].offset && cus[0].offset != data->d_size)
10546*7304104dSAndroid Build Coastguard Worker 	    {
10547*7304104dSAndroid Build Coastguard Worker 	      while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
10548*7304104dSAndroid Build Coastguard Worker 		++cus;
10549*7304104dSAndroid Build Coastguard Worker 
10550*7304104dSAndroid Build Coastguard Worker 	      if (cus[0].files == NULL
10551*7304104dSAndroid Build Coastguard Worker 		  && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
10552*7304104dSAndroid Build Coastguard Worker 		cus[0].files = (Dwarf_Files *) -1l;
10553*7304104dSAndroid Build Coastguard Worker 
10554*7304104dSAndroid Build Coastguard Worker 	      if (cus[0].files != (Dwarf_Files *) -1l)
10555*7304104dSAndroid Build Coastguard Worker 		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
10556*7304104dSAndroid Build Coastguard Worker 			 ?: "???");
10557*7304104dSAndroid Build Coastguard Worker 	    }
10558*7304104dSAndroid Build Coastguard Worker 
10559*7304104dSAndroid Build Coastguard Worker 	  printf ("%*sstart_file %u, [%u] %s\n",
10560*7304104dSAndroid Build Coastguard Worker 		  level, "", u128, u128_2, fname);
10561*7304104dSAndroid Build Coastguard Worker 	  ++level;
10562*7304104dSAndroid Build Coastguard Worker 	  break;
10563*7304104dSAndroid Build Coastguard Worker 
10564*7304104dSAndroid Build Coastguard Worker 	case DW_MACINFO_end_file:
10565*7304104dSAndroid Build Coastguard Worker 	  --level;
10566*7304104dSAndroid Build Coastguard Worker 	  printf ("%*send_file\n", level, "");
10567*7304104dSAndroid Build Coastguard Worker 	  /* Nothing more to do.  */
10568*7304104dSAndroid Build Coastguard Worker 	  break;
10569*7304104dSAndroid Build Coastguard Worker 
10570*7304104dSAndroid Build Coastguard Worker 	default:
10571*7304104dSAndroid Build Coastguard Worker 	  // XXX gcc seems to generate files with a trailing zero.
10572*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (opcode != 0 || readp != readendp))
10573*7304104dSAndroid Build Coastguard Worker 	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
10574*7304104dSAndroid Build Coastguard Worker 	  break;
10575*7304104dSAndroid Build Coastguard Worker 	}
10576*7304104dSAndroid Build Coastguard Worker     }
10577*7304104dSAndroid Build Coastguard Worker }
10578*7304104dSAndroid Build Coastguard Worker 
10579*7304104dSAndroid Build Coastguard Worker 
10580*7304104dSAndroid Build Coastguard Worker static void
print_debug_macro_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)10581*7304104dSAndroid Build Coastguard Worker print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10582*7304104dSAndroid Build Coastguard Worker 			   Ebl *ebl,
10583*7304104dSAndroid Build Coastguard Worker 			   GElf_Ehdr *ehdr __attribute__ ((unused)),
10584*7304104dSAndroid Build Coastguard Worker 			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10585*7304104dSAndroid Build Coastguard Worker {
10586*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macro, scn);
10587*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
10588*7304104dSAndroid Build Coastguard Worker     return;
10589*7304104dSAndroid Build Coastguard Worker 
10590*7304104dSAndroid Build Coastguard Worker   printf (_("\
10591*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10592*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
10593*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
10594*7304104dSAndroid Build Coastguard Worker   putc_unlocked ('\n', stdout);
10595*7304104dSAndroid Build Coastguard Worker 
10596*7304104dSAndroid Build Coastguard Worker   /* Get the source file information for all CUs.  Uses same
10597*7304104dSAndroid Build Coastguard Worker      datastructure as macinfo.  But uses offset field to directly
10598*7304104dSAndroid Build Coastguard Worker      match .debug_line offset.  And just stored in a list.  */
10599*7304104dSAndroid Build Coastguard Worker   Dwarf_Off offset;
10600*7304104dSAndroid Build Coastguard Worker   Dwarf_Off ncu = 0;
10601*7304104dSAndroid Build Coastguard Worker   size_t hsize;
10602*7304104dSAndroid Build Coastguard Worker   struct mac_culist *culist = NULL;
10603*7304104dSAndroid Build Coastguard Worker   while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
10604*7304104dSAndroid Build Coastguard Worker     {
10605*7304104dSAndroid Build Coastguard Worker       Dwarf_Die cudie;
10606*7304104dSAndroid Build Coastguard Worker       if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
10607*7304104dSAndroid Build Coastguard Worker 	continue;
10608*7304104dSAndroid Build Coastguard Worker 
10609*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute attr;
10610*7304104dSAndroid Build Coastguard Worker       if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
10611*7304104dSAndroid Build Coastguard Worker 	continue;
10612*7304104dSAndroid Build Coastguard Worker 
10613*7304104dSAndroid Build Coastguard Worker       Dwarf_Word lineoff;
10614*7304104dSAndroid Build Coastguard Worker       if (dwarf_formudata (&attr, &lineoff) != 0)
10615*7304104dSAndroid Build Coastguard Worker 	continue;
10616*7304104dSAndroid Build Coastguard Worker 
10617*7304104dSAndroid Build Coastguard Worker       struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
10618*7304104dSAndroid Build Coastguard Worker       newp->die = cudie;
10619*7304104dSAndroid Build Coastguard Worker       newp->offset = lineoff;
10620*7304104dSAndroid Build Coastguard Worker       newp->files = NULL;
10621*7304104dSAndroid Build Coastguard Worker       newp->next = culist;
10622*7304104dSAndroid Build Coastguard Worker       culist = newp;
10623*7304104dSAndroid Build Coastguard Worker     }
10624*7304104dSAndroid Build Coastguard Worker 
10625*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = (const unsigned char *) data->d_buf;
10626*7304104dSAndroid Build Coastguard Worker   const unsigned char *readendp = readp + data->d_size;
10627*7304104dSAndroid Build Coastguard Worker 
10628*7304104dSAndroid Build Coastguard Worker   while (readp < readendp)
10629*7304104dSAndroid Build Coastguard Worker     {
10630*7304104dSAndroid Build Coastguard Worker       printf (_(" Offset:             0x%" PRIx64 "\n"),
10631*7304104dSAndroid Build Coastguard Worker 	      (uint64_t) (readp - (const unsigned char *) data->d_buf));
10632*7304104dSAndroid Build Coastguard Worker 
10633*7304104dSAndroid Build Coastguard Worker       // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
10634*7304104dSAndroid Build Coastguard Worker       // optional vendor extension macro entry table.
10635*7304104dSAndroid Build Coastguard Worker       if (readp + 2 > readendp)
10636*7304104dSAndroid Build Coastguard Worker 	{
10637*7304104dSAndroid Build Coastguard Worker 	invalid_data:
10638*7304104dSAndroid Build Coastguard Worker 	  error (0, 0, _("invalid data"));
10639*7304104dSAndroid Build Coastguard Worker 	  return;
10640*7304104dSAndroid Build Coastguard Worker 	}
10641*7304104dSAndroid Build Coastguard Worker       const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
10642*7304104dSAndroid Build Coastguard Worker       printf (_(" Version:            %" PRIu16 "\n"), vers);
10643*7304104dSAndroid Build Coastguard Worker 
10644*7304104dSAndroid Build Coastguard Worker       // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
10645*7304104dSAndroid Build Coastguard Worker       // 5 when it gets standardized.
10646*7304104dSAndroid Build Coastguard Worker       if (vers != 4 && vers != 5)
10647*7304104dSAndroid Build Coastguard Worker 	{
10648*7304104dSAndroid Build Coastguard Worker 	  printf (_("  unknown version, cannot parse section\n"));
10649*7304104dSAndroid Build Coastguard Worker 	  return;
10650*7304104dSAndroid Build Coastguard Worker 	}
10651*7304104dSAndroid Build Coastguard Worker 
10652*7304104dSAndroid Build Coastguard Worker       if (readp + 1 > readendp)
10653*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
10654*7304104dSAndroid Build Coastguard Worker       const unsigned char flag = *readp++;
10655*7304104dSAndroid Build Coastguard Worker       printf (_(" Flag:               0x%" PRIx8), flag);
10656*7304104dSAndroid Build Coastguard Worker       if (flag != 0)
10657*7304104dSAndroid Build Coastguard Worker 	{
10658*7304104dSAndroid Build Coastguard Worker 	  printf (" (");
10659*7304104dSAndroid Build Coastguard Worker 	  if ((flag & 0x01) != 0)
10660*7304104dSAndroid Build Coastguard Worker 	    {
10661*7304104dSAndroid Build Coastguard Worker 	      printf ("offset_size");
10662*7304104dSAndroid Build Coastguard Worker 	      if ((flag & 0xFE) !=  0)
10663*7304104dSAndroid Build Coastguard Worker 		printf (", ");
10664*7304104dSAndroid Build Coastguard Worker 	    }
10665*7304104dSAndroid Build Coastguard Worker 	  if ((flag & 0x02) != 0)
10666*7304104dSAndroid Build Coastguard Worker 	    {
10667*7304104dSAndroid Build Coastguard Worker 	      printf ("debug_line_offset");
10668*7304104dSAndroid Build Coastguard Worker 	      if ((flag & 0xFC) !=  0)
10669*7304104dSAndroid Build Coastguard Worker 		printf (", ");
10670*7304104dSAndroid Build Coastguard Worker 	    }
10671*7304104dSAndroid Build Coastguard Worker 	  if ((flag & 0x04) != 0)
10672*7304104dSAndroid Build Coastguard Worker 	    {
10673*7304104dSAndroid Build Coastguard Worker 	      printf ("operands_table");
10674*7304104dSAndroid Build Coastguard Worker 	      if ((flag & 0xF8) !=  0)
10675*7304104dSAndroid Build Coastguard Worker 		printf (", ");
10676*7304104dSAndroid Build Coastguard Worker 	    }
10677*7304104dSAndroid Build Coastguard Worker 	  if ((flag & 0xF8) != 0)
10678*7304104dSAndroid Build Coastguard Worker 	    printf ("unknown");
10679*7304104dSAndroid Build Coastguard Worker 	  printf (")");
10680*7304104dSAndroid Build Coastguard Worker 	}
10681*7304104dSAndroid Build Coastguard Worker       printf ("\n");
10682*7304104dSAndroid Build Coastguard Worker 
10683*7304104dSAndroid Build Coastguard Worker       unsigned int offset_len = (flag & 0x01) ? 8 : 4;
10684*7304104dSAndroid Build Coastguard Worker       printf (_(" Offset length:      %" PRIu8 "\n"), offset_len);
10685*7304104dSAndroid Build Coastguard Worker       Dwarf_Off line_offset = -1;
10686*7304104dSAndroid Build Coastguard Worker       if (flag & 0x02)
10687*7304104dSAndroid Build Coastguard Worker 	{
10688*7304104dSAndroid Build Coastguard Worker 	  if (offset_len == 8)
10689*7304104dSAndroid Build Coastguard Worker 	    line_offset = read_8ubyte_unaligned_inc (dbg, readp);
10690*7304104dSAndroid Build Coastguard Worker 	  else
10691*7304104dSAndroid Build Coastguard Worker 	    line_offset = read_4ubyte_unaligned_inc (dbg, readp);
10692*7304104dSAndroid Build Coastguard Worker 	  printf (_(" .debug_line offset: 0x%" PRIx64 "\n"),
10693*7304104dSAndroid Build Coastguard Worker 		  line_offset);
10694*7304104dSAndroid Build Coastguard Worker 	}
10695*7304104dSAndroid Build Coastguard Worker 
10696*7304104dSAndroid Build Coastguard Worker       struct mac_culist *cu = NULL;
10697*7304104dSAndroid Build Coastguard Worker       if (line_offset != (Dwarf_Off) -1)
10698*7304104dSAndroid Build Coastguard Worker 	{
10699*7304104dSAndroid Build Coastguard Worker 	  cu = culist;
10700*7304104dSAndroid Build Coastguard Worker 	  while (cu != NULL && line_offset != cu->offset)
10701*7304104dSAndroid Build Coastguard Worker 	    cu = cu->next;
10702*7304104dSAndroid Build Coastguard Worker 	}
10703*7304104dSAndroid Build Coastguard Worker 
10704*7304104dSAndroid Build Coastguard Worker       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
10705*7304104dSAndroid Build Coastguard Worker 							       ? cu->die.cu
10706*7304104dSAndroid Build Coastguard Worker 							       : NULL));
10707*7304104dSAndroid Build Coastguard Worker 
10708*7304104dSAndroid Build Coastguard Worker       const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
10709*7304104dSAndroid Build Coastguard Worker       memset (vendor, 0, sizeof vendor);
10710*7304104dSAndroid Build Coastguard Worker       if (flag & 0x04)
10711*7304104dSAndroid Build Coastguard Worker 	{
10712*7304104dSAndroid Build Coastguard Worker 	  // 1 byte length, for each item, 1 byte opcode, uleb128 number
10713*7304104dSAndroid Build Coastguard Worker 	  // of arguments, for each argument 1 byte form code.
10714*7304104dSAndroid Build Coastguard Worker 	  if (readp + 1 > readendp)
10715*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
10716*7304104dSAndroid Build Coastguard Worker 	  unsigned int tlen = *readp++;
10717*7304104dSAndroid Build Coastguard Worker 	  printf (_("  extension opcode table, %" PRIu8 " items:\n"),
10718*7304104dSAndroid Build Coastguard Worker 		  tlen);
10719*7304104dSAndroid Build Coastguard Worker 	  for (unsigned int i = 0; i < tlen; i++)
10720*7304104dSAndroid Build Coastguard Worker 	    {
10721*7304104dSAndroid Build Coastguard Worker 	      if (readp + 1 > readendp)
10722*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10723*7304104dSAndroid Build Coastguard Worker 	      unsigned int opcode = *readp++;
10724*7304104dSAndroid Build Coastguard Worker 	      printf (_("    [%" PRIx8 "]"), opcode);
10725*7304104dSAndroid Build Coastguard Worker 	      if (opcode < DW_MACRO_lo_user
10726*7304104dSAndroid Build Coastguard Worker 		  || opcode > DW_MACRO_hi_user)
10727*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10728*7304104dSAndroid Build Coastguard Worker 	      // Record the start of description for this vendor opcode.
10729*7304104dSAndroid Build Coastguard Worker 	      // uleb128 nr args, 1 byte per arg form.
10730*7304104dSAndroid Build Coastguard Worker 	      vendor[opcode - DW_MACRO_lo_user] = readp;
10731*7304104dSAndroid Build Coastguard Worker 	      if (readp + 1 > readendp)
10732*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10733*7304104dSAndroid Build Coastguard Worker 	      unsigned int args = *readp++;
10734*7304104dSAndroid Build Coastguard Worker 	      if (args > 0)
10735*7304104dSAndroid Build Coastguard Worker 		{
10736*7304104dSAndroid Build Coastguard Worker 		  printf (_(" %" PRIu8 " arguments:"), args);
10737*7304104dSAndroid Build Coastguard Worker 		  while (args > 0)
10738*7304104dSAndroid Build Coastguard Worker 		    {
10739*7304104dSAndroid Build Coastguard Worker 		      if (readp + 1 > readendp)
10740*7304104dSAndroid Build Coastguard Worker 			goto invalid_data;
10741*7304104dSAndroid Build Coastguard Worker 		      unsigned int form = *readp++;
10742*7304104dSAndroid Build Coastguard Worker 		      printf (" %s", dwarf_form_name (form));
10743*7304104dSAndroid Build Coastguard Worker 		      if (! libdw_valid_user_form (form))
10744*7304104dSAndroid Build Coastguard Worker 			goto invalid_data;
10745*7304104dSAndroid Build Coastguard Worker 		      args--;
10746*7304104dSAndroid Build Coastguard Worker 		      if (args > 0)
10747*7304104dSAndroid Build Coastguard Worker 			putchar_unlocked (',');
10748*7304104dSAndroid Build Coastguard Worker 		    }
10749*7304104dSAndroid Build Coastguard Worker 		}
10750*7304104dSAndroid Build Coastguard Worker 	      else
10751*7304104dSAndroid Build Coastguard Worker 		printf (_(" no arguments."));
10752*7304104dSAndroid Build Coastguard Worker 	      putchar_unlocked ('\n');
10753*7304104dSAndroid Build Coastguard Worker 	    }
10754*7304104dSAndroid Build Coastguard Worker 	}
10755*7304104dSAndroid Build Coastguard Worker       putchar_unlocked ('\n');
10756*7304104dSAndroid Build Coastguard Worker 
10757*7304104dSAndroid Build Coastguard Worker       int level = 1;
10758*7304104dSAndroid Build Coastguard Worker       if (readp + 1 > readendp)
10759*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
10760*7304104dSAndroid Build Coastguard Worker       unsigned int opcode = *readp++;
10761*7304104dSAndroid Build Coastguard Worker       while (opcode != 0)
10762*7304104dSAndroid Build Coastguard Worker 	{
10763*7304104dSAndroid Build Coastguard Worker 	  unsigned int u128;
10764*7304104dSAndroid Build Coastguard Worker 	  unsigned int u128_2;
10765*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *endp;
10766*7304104dSAndroid Build Coastguard Worker 	  uint64_t off;
10767*7304104dSAndroid Build Coastguard Worker 
10768*7304104dSAndroid Build Coastguard Worker           switch (opcode)
10769*7304104dSAndroid Build Coastguard Worker             {
10770*7304104dSAndroid Build Coastguard Worker             case DW_MACRO_start_file:
10771*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10772*7304104dSAndroid Build Coastguard Worker 	      if (readp >= readendp)
10773*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10774*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128_2, readp, readendp);
10775*7304104dSAndroid Build Coastguard Worker 
10776*7304104dSAndroid Build Coastguard Worker 	      /* Find the CU DIE that matches this line offset.  */
10777*7304104dSAndroid Build Coastguard Worker 	      const char *fname = "???";
10778*7304104dSAndroid Build Coastguard Worker 	      if (cu != NULL)
10779*7304104dSAndroid Build Coastguard Worker 		{
10780*7304104dSAndroid Build Coastguard Worker 		  if (cu->files == NULL
10781*7304104dSAndroid Build Coastguard Worker 		      && dwarf_getsrcfiles (&cu->die, &cu->files,
10782*7304104dSAndroid Build Coastguard Worker 					    NULL) != 0)
10783*7304104dSAndroid Build Coastguard Worker 		    cu->files = (Dwarf_Files *) -1l;
10784*7304104dSAndroid Build Coastguard Worker 
10785*7304104dSAndroid Build Coastguard Worker 		  if (cu->files != (Dwarf_Files *) -1l)
10786*7304104dSAndroid Build Coastguard Worker 		    fname = (dwarf_filesrc (cu->files, u128_2,
10787*7304104dSAndroid Build Coastguard Worker 					    NULL, NULL) ?: "???");
10788*7304104dSAndroid Build Coastguard Worker 		}
10789*7304104dSAndroid Build Coastguard Worker 	      printf ("%*sstart_file %u, [%u] %s\n",
10790*7304104dSAndroid Build Coastguard Worker 		      level, "", u128, u128_2, fname);
10791*7304104dSAndroid Build Coastguard Worker 	      ++level;
10792*7304104dSAndroid Build Coastguard Worker 	      break;
10793*7304104dSAndroid Build Coastguard Worker 
10794*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_end_file:
10795*7304104dSAndroid Build Coastguard Worker 	      --level;
10796*7304104dSAndroid Build Coastguard Worker 	      printf ("%*send_file\n", level, "");
10797*7304104dSAndroid Build Coastguard Worker 	      break;
10798*7304104dSAndroid Build Coastguard Worker 
10799*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_define:
10800*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10801*7304104dSAndroid Build Coastguard Worker 	      endp = memchr (readp, '\0', readendp - readp);
10802*7304104dSAndroid Build Coastguard Worker 	      if (endp == NULL)
10803*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10804*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#define %s, line %u\n",
10805*7304104dSAndroid Build Coastguard Worker 		      level, "", readp, u128);
10806*7304104dSAndroid Build Coastguard Worker 	      readp = endp + 1;
10807*7304104dSAndroid Build Coastguard Worker 	      break;
10808*7304104dSAndroid Build Coastguard Worker 
10809*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_undef:
10810*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10811*7304104dSAndroid Build Coastguard Worker 	      endp = memchr (readp, '\0', readendp - readp);
10812*7304104dSAndroid Build Coastguard Worker 	      if (endp == NULL)
10813*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10814*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#undef %s, line %u\n",
10815*7304104dSAndroid Build Coastguard Worker 		      level, "", readp, u128);
10816*7304104dSAndroid Build Coastguard Worker 	      readp = endp + 1;
10817*7304104dSAndroid Build Coastguard Worker 	      break;
10818*7304104dSAndroid Build Coastguard Worker 
10819*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_define_strp:
10820*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10821*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10822*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10823*7304104dSAndroid Build Coastguard Worker 	      if (offset_len == 8)
10824*7304104dSAndroid Build Coastguard Worker 		off = read_8ubyte_unaligned_inc (dbg, readp);
10825*7304104dSAndroid Build Coastguard Worker 	      else
10826*7304104dSAndroid Build Coastguard Worker 		off = read_4ubyte_unaligned_inc (dbg, readp);
10827*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#define %s, line %u (indirect)\n",
10828*7304104dSAndroid Build Coastguard Worker 		      level, "", dwarf_getstring (dbg, off, NULL), u128);
10829*7304104dSAndroid Build Coastguard Worker 	      break;
10830*7304104dSAndroid Build Coastguard Worker 
10831*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_undef_strp:
10832*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10833*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10834*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10835*7304104dSAndroid Build Coastguard Worker 	      if (offset_len == 8)
10836*7304104dSAndroid Build Coastguard Worker 		off = read_8ubyte_unaligned_inc (dbg, readp);
10837*7304104dSAndroid Build Coastguard Worker 	      else
10838*7304104dSAndroid Build Coastguard Worker 		off = read_4ubyte_unaligned_inc (dbg, readp);
10839*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#undef %s, line %u (indirect)\n",
10840*7304104dSAndroid Build Coastguard Worker 		      level, "", dwarf_getstring (dbg, off, NULL), u128);
10841*7304104dSAndroid Build Coastguard Worker 	      break;
10842*7304104dSAndroid Build Coastguard Worker 
10843*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_import:
10844*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10845*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10846*7304104dSAndroid Build Coastguard Worker 	      if (offset_len == 8)
10847*7304104dSAndroid Build Coastguard Worker 		off = read_8ubyte_unaligned_inc (dbg, readp);
10848*7304104dSAndroid Build Coastguard Worker 	      else
10849*7304104dSAndroid Build Coastguard Worker 		off = read_4ubyte_unaligned_inc (dbg, readp);
10850*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#include offset 0x%" PRIx64 "\n",
10851*7304104dSAndroid Build Coastguard Worker 		      level, "", off);
10852*7304104dSAndroid Build Coastguard Worker 	      break;
10853*7304104dSAndroid Build Coastguard Worker 
10854*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_define_sup:
10855*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10856*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10857*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10858*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#define ", level, "");
10859*7304104dSAndroid Build Coastguard Worker 	      readp =  print_form_data (dbg, DW_FORM_strp_sup,
10860*7304104dSAndroid Build Coastguard Worker 					readp, readendp, offset_len,
10861*7304104dSAndroid Build Coastguard Worker 					str_offsets_base);
10862*7304104dSAndroid Build Coastguard Worker 	      printf (", line %u (sup)\n", u128);
10863*7304104dSAndroid Build Coastguard Worker 	      break;
10864*7304104dSAndroid Build Coastguard Worker 
10865*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_undef_sup:
10866*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10867*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10868*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10869*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#undef ", level, "");
10870*7304104dSAndroid Build Coastguard Worker 	      readp =  print_form_data (dbg, DW_FORM_strp_sup,
10871*7304104dSAndroid Build Coastguard Worker 					readp, readendp, offset_len,
10872*7304104dSAndroid Build Coastguard Worker 					str_offsets_base);
10873*7304104dSAndroid Build Coastguard Worker 	      printf (", line %u (sup)\n", u128);
10874*7304104dSAndroid Build Coastguard Worker 	      break;
10875*7304104dSAndroid Build Coastguard Worker 
10876*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_import_sup:
10877*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10878*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10879*7304104dSAndroid Build Coastguard Worker 	      if (offset_len == 8)
10880*7304104dSAndroid Build Coastguard Worker 		off = read_8ubyte_unaligned_inc (dbg, readp);
10881*7304104dSAndroid Build Coastguard Worker 	      else
10882*7304104dSAndroid Build Coastguard Worker 		off = read_4ubyte_unaligned_inc (dbg, readp);
10883*7304104dSAndroid Build Coastguard Worker 	      // XXX Needs support for reading from supplementary object file.
10884*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
10885*7304104dSAndroid Build Coastguard Worker 		      level, "", off);
10886*7304104dSAndroid Build Coastguard Worker 	      break;
10887*7304104dSAndroid Build Coastguard Worker 
10888*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_define_strx:
10889*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10890*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10891*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10892*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#define ", level, "");
10893*7304104dSAndroid Build Coastguard Worker 	      readp =  print_form_data (dbg, DW_FORM_strx,
10894*7304104dSAndroid Build Coastguard Worker 					readp, readendp, offset_len,
10895*7304104dSAndroid Build Coastguard Worker 					str_offsets_base);
10896*7304104dSAndroid Build Coastguard Worker 	      printf (", line %u (strx)\n", u128);
10897*7304104dSAndroid Build Coastguard Worker 	      break;
10898*7304104dSAndroid Build Coastguard Worker 
10899*7304104dSAndroid Build Coastguard Worker 	    case DW_MACRO_undef_strx:
10900*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, readp, readendp);
10901*7304104dSAndroid Build Coastguard Worker 	      if (readp + offset_len > readendp)
10902*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10903*7304104dSAndroid Build Coastguard Worker 	      printf ("%*s#undef ", level, "");
10904*7304104dSAndroid Build Coastguard Worker 	      readp =  print_form_data (dbg, DW_FORM_strx,
10905*7304104dSAndroid Build Coastguard Worker 					readp, readendp, offset_len,
10906*7304104dSAndroid Build Coastguard Worker 					str_offsets_base);
10907*7304104dSAndroid Build Coastguard Worker 	      printf (", line %u (strx)\n", u128);
10908*7304104dSAndroid Build Coastguard Worker 	      break;
10909*7304104dSAndroid Build Coastguard Worker 
10910*7304104dSAndroid Build Coastguard Worker 	    default:
10911*7304104dSAndroid Build Coastguard Worker 	      printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
10912*7304104dSAndroid Build Coastguard Worker 	      if (opcode < DW_MACRO_lo_user
10913*7304104dSAndroid Build Coastguard Worker 		  || opcode > DW_MACRO_lo_user
10914*7304104dSAndroid Build Coastguard Worker 		  || vendor[opcode - DW_MACRO_lo_user] == NULL)
10915*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
10916*7304104dSAndroid Build Coastguard Worker 
10917*7304104dSAndroid Build Coastguard Worker 	      const unsigned char *op_desc;
10918*7304104dSAndroid Build Coastguard Worker 	      op_desc = vendor[opcode - DW_MACRO_lo_user];
10919*7304104dSAndroid Build Coastguard Worker 
10920*7304104dSAndroid Build Coastguard Worker 	      // Just skip the arguments, we cannot really interpret them,
10921*7304104dSAndroid Build Coastguard Worker 	      // but print as much as we can.
10922*7304104dSAndroid Build Coastguard Worker 	      unsigned int args = *op_desc++;
10923*7304104dSAndroid Build Coastguard Worker 	      while (args > 0 && readp < readendp)
10924*7304104dSAndroid Build Coastguard Worker 		{
10925*7304104dSAndroid Build Coastguard Worker 		  unsigned int form = *op_desc++;
10926*7304104dSAndroid Build Coastguard Worker 		  readp = print_form_data (dbg, form, readp, readendp,
10927*7304104dSAndroid Build Coastguard Worker 					   offset_len, str_offsets_base);
10928*7304104dSAndroid Build Coastguard Worker 		  args--;
10929*7304104dSAndroid Build Coastguard Worker 		  if (args > 0)
10930*7304104dSAndroid Build Coastguard Worker 		    printf (", ");
10931*7304104dSAndroid Build Coastguard Worker 		}
10932*7304104dSAndroid Build Coastguard Worker 	      putchar_unlocked ('\n');
10933*7304104dSAndroid Build Coastguard Worker 	    }
10934*7304104dSAndroid Build Coastguard Worker 
10935*7304104dSAndroid Build Coastguard Worker 	  if (readp + 1 > readendp)
10936*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
10937*7304104dSAndroid Build Coastguard Worker 	  opcode = *readp++;
10938*7304104dSAndroid Build Coastguard Worker 	  if (opcode == 0)
10939*7304104dSAndroid Build Coastguard Worker 	    putchar_unlocked ('\n');
10940*7304104dSAndroid Build Coastguard Worker 	}
10941*7304104dSAndroid Build Coastguard Worker     }
10942*7304104dSAndroid Build Coastguard Worker }
10943*7304104dSAndroid Build Coastguard Worker 
10944*7304104dSAndroid Build Coastguard Worker 
10945*7304104dSAndroid Build Coastguard Worker /* Callback for printing global names.  */
10946*7304104dSAndroid Build Coastguard Worker static int
print_pubnames(Dwarf * dbg,Dwarf_Global * global,void * arg)10947*7304104dSAndroid Build Coastguard Worker print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
10948*7304104dSAndroid Build Coastguard Worker 		void *arg)
10949*7304104dSAndroid Build Coastguard Worker {
10950*7304104dSAndroid Build Coastguard Worker   int *np = (int *) arg;
10951*7304104dSAndroid Build Coastguard Worker 
10952*7304104dSAndroid Build Coastguard Worker   printf (_(" [%5d] DIE offset: %6" PRId64
10953*7304104dSAndroid Build Coastguard Worker 		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
10954*7304104dSAndroid Build Coastguard Worker 	  (*np)++, global->die_offset, global->cu_offset, global->name);
10955*7304104dSAndroid Build Coastguard Worker 
10956*7304104dSAndroid Build Coastguard Worker   return 0;
10957*7304104dSAndroid Build Coastguard Worker }
10958*7304104dSAndroid Build Coastguard Worker 
10959*7304104dSAndroid Build Coastguard Worker 
10960*7304104dSAndroid Build Coastguard Worker /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
10961*7304104dSAndroid Build Coastguard Worker static void
print_debug_pubnames_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)10962*7304104dSAndroid Build Coastguard Worker print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10963*7304104dSAndroid Build Coastguard Worker 			      Ebl *ebl,
10964*7304104dSAndroid Build Coastguard Worker 			      GElf_Ehdr *ehdr __attribute__ ((unused)),
10965*7304104dSAndroid Build Coastguard Worker 			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
10966*7304104dSAndroid Build Coastguard Worker {
10967*7304104dSAndroid Build Coastguard Worker   /* Check section actually exists.  */
10968*7304104dSAndroid Build Coastguard Worker   if (get_debug_elf_data (dbg, ebl, IDX_debug_pubnames, scn) == NULL)
10969*7304104dSAndroid Build Coastguard Worker       return;
10970*7304104dSAndroid Build Coastguard Worker 
10971*7304104dSAndroid Build Coastguard Worker   printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
10972*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
10973*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
10974*7304104dSAndroid Build Coastguard Worker 
10975*7304104dSAndroid Build Coastguard Worker   int n = 0;
10976*7304104dSAndroid Build Coastguard Worker   (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
10977*7304104dSAndroid Build Coastguard Worker }
10978*7304104dSAndroid Build Coastguard Worker 
10979*7304104dSAndroid Build Coastguard Worker /* Print the content of the DWARF string section '.debug_str'
10980*7304104dSAndroid Build Coastguard Worker    or 'debug_line_str'.  */
10981*7304104dSAndroid Build Coastguard Worker static void
print_debug_str_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)10982*7304104dSAndroid Build Coastguard Worker print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
10983*7304104dSAndroid Build Coastguard Worker 			 Ebl *ebl,
10984*7304104dSAndroid Build Coastguard Worker 			 GElf_Ehdr *ehdr __attribute__ ((unused)),
10985*7304104dSAndroid Build Coastguard Worker 			 Elf_Scn *scn, GElf_Shdr *shdr,
10986*7304104dSAndroid Build Coastguard Worker 			 Dwarf *dbg __attribute__ ((unused)))
10987*7304104dSAndroid Build Coastguard Worker {
10988*7304104dSAndroid Build Coastguard Worker   const char *name = section_name (ebl, shdr);
10989*7304104dSAndroid Build Coastguard Worker   int idx = ((name != NULL && strstr (name, "debug_line_str") != NULL)
10990*7304104dSAndroid Build Coastguard Worker 	     ? IDX_debug_line_str : IDX_debug_str);
10991*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, idx, scn);
10992*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
10993*7304104dSAndroid Build Coastguard Worker     return;
10994*7304104dSAndroid Build Coastguard Worker 
10995*7304104dSAndroid Build Coastguard Worker   const size_t sh_size = data->d_size;
10996*7304104dSAndroid Build Coastguard Worker 
10997*7304104dSAndroid Build Coastguard Worker   /* Compute floor(log16(shdr->sh_size)).  */
10998*7304104dSAndroid Build Coastguard Worker   GElf_Addr tmp = sh_size;
10999*7304104dSAndroid Build Coastguard Worker   int digits = 1;
11000*7304104dSAndroid Build Coastguard Worker   while (tmp >= 16)
11001*7304104dSAndroid Build Coastguard Worker     {
11002*7304104dSAndroid Build Coastguard Worker       ++digits;
11003*7304104dSAndroid Build Coastguard Worker       tmp >>= 4;
11004*7304104dSAndroid Build Coastguard Worker     }
11005*7304104dSAndroid Build Coastguard Worker   digits = MAX (4, digits);
11006*7304104dSAndroid Build Coastguard Worker 
11007*7304104dSAndroid Build Coastguard Worker   printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
11008*7304104dSAndroid Build Coastguard Worker 		   " %*s  String\n"),
11009*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn),
11010*7304104dSAndroid Build Coastguard Worker 	  section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
11011*7304104dSAndroid Build Coastguard Worker 	  /* TRANS: the debugstr| prefix makes the string unique.  */
11012*7304104dSAndroid Build Coastguard Worker 	  digits + 2, sgettext ("debugstr|Offset"));
11013*7304104dSAndroid Build Coastguard Worker 
11014*7304104dSAndroid Build Coastguard Worker   Dwarf_Off offset = 0;
11015*7304104dSAndroid Build Coastguard Worker   while (offset < sh_size)
11016*7304104dSAndroid Build Coastguard Worker     {
11017*7304104dSAndroid Build Coastguard Worker       size_t len;
11018*7304104dSAndroid Build Coastguard Worker       const char *str = (const char *) data->d_buf + offset;
11019*7304104dSAndroid Build Coastguard Worker       const char *endp = memchr (str, '\0', sh_size - offset);
11020*7304104dSAndroid Build Coastguard Worker       if (unlikely (endp == NULL))
11021*7304104dSAndroid Build Coastguard Worker 	{
11022*7304104dSAndroid Build Coastguard Worker 	  printf (_(" *** error, missing string terminator\n"));
11023*7304104dSAndroid Build Coastguard Worker 	  break;
11024*7304104dSAndroid Build Coastguard Worker 	}
11025*7304104dSAndroid Build Coastguard Worker 
11026*7304104dSAndroid Build Coastguard Worker       printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
11027*7304104dSAndroid Build Coastguard Worker       len = endp - str;
11028*7304104dSAndroid Build Coastguard Worker       offset += len + 1;
11029*7304104dSAndroid Build Coastguard Worker     }
11030*7304104dSAndroid Build Coastguard Worker }
11031*7304104dSAndroid Build Coastguard Worker 
11032*7304104dSAndroid Build Coastguard Worker static void
print_debug_str_offsets_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)11033*7304104dSAndroid Build Coastguard Worker print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
11034*7304104dSAndroid Build Coastguard Worker 				 Ebl *ebl,
11035*7304104dSAndroid Build Coastguard Worker 				 GElf_Ehdr *ehdr __attribute__ ((unused)),
11036*7304104dSAndroid Build Coastguard Worker 				 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
11037*7304104dSAndroid Build Coastguard Worker {
11038*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_str_offsets, scn);
11039*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
11040*7304104dSAndroid Build Coastguard Worker     return;
11041*7304104dSAndroid Build Coastguard Worker 
11042*7304104dSAndroid Build Coastguard Worker   printf (_("\
11043*7304104dSAndroid Build Coastguard Worker \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
11044*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
11045*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset);
11046*7304104dSAndroid Build Coastguard Worker 
11047*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_size == 0)
11048*7304104dSAndroid Build Coastguard Worker     return;
11049*7304104dSAndroid Build Coastguard Worker 
11050*7304104dSAndroid Build Coastguard Worker   size_t idx = 0;
11051*7304104dSAndroid Build Coastguard Worker   sort_listptr (&known_stroffbases, "str_offsets");
11052*7304104dSAndroid Build Coastguard Worker 
11053*7304104dSAndroid Build Coastguard Worker   const unsigned char *start = (const unsigned char *) data->d_buf;
11054*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = start;
11055*7304104dSAndroid Build Coastguard Worker   const unsigned char *readendp = ((const unsigned char *) data->d_buf
11056*7304104dSAndroid Build Coastguard Worker 				   + data->d_size);
11057*7304104dSAndroid Build Coastguard Worker 
11058*7304104dSAndroid Build Coastguard Worker   while (readp < readendp)
11059*7304104dSAndroid Build Coastguard Worker     {
11060*7304104dSAndroid Build Coastguard Worker       /* Most string offset tables will have a header.  For split
11061*7304104dSAndroid Build Coastguard Worker 	 dwarf unit GNU DebugFission didn't add one.  But they were
11062*7304104dSAndroid Build Coastguard Worker 	 also only defined for split units (main or skeleton units
11063*7304104dSAndroid Build Coastguard Worker 	 didn't have indirect strings).  So if we don't have a
11064*7304104dSAndroid Build Coastguard Worker 	 DW_AT_str_offsets_base at all and this is offset zero, then
11065*7304104dSAndroid Build Coastguard Worker 	 just start printing offsets immediately, if this is a .dwo
11066*7304104dSAndroid Build Coastguard Worker 	 section.  */
11067*7304104dSAndroid Build Coastguard Worker       Dwarf_Off off = (Dwarf_Off) (readp
11068*7304104dSAndroid Build Coastguard Worker 				   - (const unsigned char *) data->d_buf);
11069*7304104dSAndroid Build Coastguard Worker 
11070*7304104dSAndroid Build Coastguard Worker       printf ("Table at offset %" PRIx64 " ", off);
11071*7304104dSAndroid Build Coastguard Worker 
11072*7304104dSAndroid Build Coastguard Worker       struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
11073*7304104dSAndroid Build Coastguard Worker       const unsigned char *next_unitp = readendp;
11074*7304104dSAndroid Build Coastguard Worker       uint8_t offset_size;
11075*7304104dSAndroid Build Coastguard Worker       bool has_header;
11076*7304104dSAndroid Build Coastguard Worker       if (listptr == NULL)
11077*7304104dSAndroid Build Coastguard Worker 	{
11078*7304104dSAndroid Build Coastguard Worker 	  /* This can happen for .dwo files.  There is only an header
11079*7304104dSAndroid Build Coastguard Worker 	     in the case this is a version 5 split DWARF file.  */
11080*7304104dSAndroid Build Coastguard Worker 	  Dwarf_CU *cu;
11081*7304104dSAndroid Build Coastguard Worker 	  uint8_t unit_type;
11082*7304104dSAndroid Build Coastguard Worker 	  if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
11083*7304104dSAndroid Build Coastguard Worker 			       NULL, NULL) != 0)
11084*7304104dSAndroid Build Coastguard Worker 	    {
11085*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, "Warning: Cannot find any DWARF unit.");
11086*7304104dSAndroid Build Coastguard Worker 	      /* Just guess some values.  */
11087*7304104dSAndroid Build Coastguard Worker 	      has_header = false;
11088*7304104dSAndroid Build Coastguard Worker 	      offset_size = 4;
11089*7304104dSAndroid Build Coastguard Worker 	    }
11090*7304104dSAndroid Build Coastguard Worker 	  else if (off == 0
11091*7304104dSAndroid Build Coastguard Worker 		   && (unit_type == DW_UT_split_type
11092*7304104dSAndroid Build Coastguard Worker 		       || unit_type == DW_UT_split_compile))
11093*7304104dSAndroid Build Coastguard Worker 	    {
11094*7304104dSAndroid Build Coastguard Worker 	      has_header = cu->version > 4;
11095*7304104dSAndroid Build Coastguard Worker 	      offset_size = cu->offset_size;
11096*7304104dSAndroid Build Coastguard Worker 	    }
11097*7304104dSAndroid Build Coastguard Worker 	  else
11098*7304104dSAndroid Build Coastguard Worker 	    {
11099*7304104dSAndroid Build Coastguard Worker 	      error (0, 0,
11100*7304104dSAndroid Build Coastguard Worker 		     "Warning: No CU references .debug_str_offsets after %"
11101*7304104dSAndroid Build Coastguard Worker 		     PRIx64, off);
11102*7304104dSAndroid Build Coastguard Worker 	      has_header = cu->version > 4;
11103*7304104dSAndroid Build Coastguard Worker 	      offset_size = cu->offset_size;
11104*7304104dSAndroid Build Coastguard Worker 	    }
11105*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
11106*7304104dSAndroid Build Coastguard Worker 	}
11107*7304104dSAndroid Build Coastguard Worker       else
11108*7304104dSAndroid Build Coastguard Worker 	{
11109*7304104dSAndroid Build Coastguard Worker 	  /* This must be DWARF5, since GNU DebugFission didn't define
11110*7304104dSAndroid Build Coastguard Worker 	     DW_AT_str_offsets_base.  */
11111*7304104dSAndroid Build Coastguard Worker 	  has_header = true;
11112*7304104dSAndroid Build Coastguard Worker 
11113*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Die cudie;
11114*7304104dSAndroid Build Coastguard Worker 	  if (dwarf_cu_die (listptr->cu, &cudie,
11115*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL, NULL, NULL,
11116*7304104dSAndroid Build Coastguard Worker 			    NULL, NULL) == NULL)
11117*7304104dSAndroid Build Coastguard Worker 	    printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
11118*7304104dSAndroid Build Coastguard Worker 	  else
11119*7304104dSAndroid Build Coastguard Worker 	    printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
11120*7304104dSAndroid Build Coastguard Worker 	}
11121*7304104dSAndroid Build Coastguard Worker 
11122*7304104dSAndroid Build Coastguard Worker       if (has_header)
11123*7304104dSAndroid Build Coastguard Worker 	{
11124*7304104dSAndroid Build Coastguard Worker 	  uint64_t unit_length;
11125*7304104dSAndroid Build Coastguard Worker 	  uint16_t version;
11126*7304104dSAndroid Build Coastguard Worker 	  uint16_t padding;
11127*7304104dSAndroid Build Coastguard Worker 
11128*7304104dSAndroid Build Coastguard Worker 	  unit_length = read_4ubyte_unaligned_inc (dbg, readp);
11129*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (unit_length == 0xffffffff))
11130*7304104dSAndroid Build Coastguard Worker 	    {
11131*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (readp > readendp - 8))
11132*7304104dSAndroid Build Coastguard Worker 		{
11133*7304104dSAndroid Build Coastguard Worker 		invalid_data:
11134*7304104dSAndroid Build Coastguard Worker 		  error (0, 0, "Invalid data");
11135*7304104dSAndroid Build Coastguard Worker 		  return;
11136*7304104dSAndroid Build Coastguard Worker 		}
11137*7304104dSAndroid Build Coastguard Worker 	      unit_length = read_8ubyte_unaligned_inc (dbg, readp);
11138*7304104dSAndroid Build Coastguard Worker 	      offset_size = 8;
11139*7304104dSAndroid Build Coastguard Worker 	    }
11140*7304104dSAndroid Build Coastguard Worker 	  else
11141*7304104dSAndroid Build Coastguard Worker 	    offset_size = 4;
11142*7304104dSAndroid Build Coastguard Worker 
11143*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
11144*7304104dSAndroid Build Coastguard Worker 	  printf (_(" Length:        %8" PRIu64 "\n"),
11145*7304104dSAndroid Build Coastguard Worker 		  unit_length);
11146*7304104dSAndroid Build Coastguard Worker 	  printf (_(" Offset size:   %8" PRIu8 "\n"),
11147*7304104dSAndroid Build Coastguard Worker 		  offset_size);
11148*7304104dSAndroid Build Coastguard Worker 
11149*7304104dSAndroid Build Coastguard Worker 	  /* We need at least 2-bytes (version) + 2-bytes (padding) =
11150*7304104dSAndroid Build Coastguard Worker 	     4 bytes to complete the header.  And this unit cannot go
11151*7304104dSAndroid Build Coastguard Worker 	     beyond the section data.  */
11152*7304104dSAndroid Build Coastguard Worker 	  if (readp > readendp - 4
11153*7304104dSAndroid Build Coastguard Worker 	      || unit_length < 4
11154*7304104dSAndroid Build Coastguard Worker 	      || unit_length > (uint64_t) (readendp - readp))
11155*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
11156*7304104dSAndroid Build Coastguard Worker 
11157*7304104dSAndroid Build Coastguard Worker 	  next_unitp = readp + unit_length;
11158*7304104dSAndroid Build Coastguard Worker 
11159*7304104dSAndroid Build Coastguard Worker 	  version = read_2ubyte_unaligned_inc (dbg, readp);
11160*7304104dSAndroid Build Coastguard Worker 	  printf (_(" DWARF version: %8" PRIu16 "\n"), version);
11161*7304104dSAndroid Build Coastguard Worker 
11162*7304104dSAndroid Build Coastguard Worker 	  if (version != 5)
11163*7304104dSAndroid Build Coastguard Worker 	    {
11164*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("Unknown version"));
11165*7304104dSAndroid Build Coastguard Worker 	      goto next_unit;
11166*7304104dSAndroid Build Coastguard Worker 	    }
11167*7304104dSAndroid Build Coastguard Worker 
11168*7304104dSAndroid Build Coastguard Worker 	  padding = read_2ubyte_unaligned_inc (dbg, readp);
11169*7304104dSAndroid Build Coastguard Worker 	  printf (_(" Padding:       %8" PRIx16 "\n"), padding);
11170*7304104dSAndroid Build Coastguard Worker 
11171*7304104dSAndroid Build Coastguard Worker 	  if (listptr != NULL
11172*7304104dSAndroid Build Coastguard Worker 	      && listptr->offset != (Dwarf_Off) (readp - start))
11173*7304104dSAndroid Build Coastguard Worker 	    {
11174*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, "String offsets index doesn't start after header");
11175*7304104dSAndroid Build Coastguard Worker 	      goto next_unit;
11176*7304104dSAndroid Build Coastguard Worker 	    }
11177*7304104dSAndroid Build Coastguard Worker 
11178*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
11179*7304104dSAndroid Build Coastguard Worker 	}
11180*7304104dSAndroid Build Coastguard Worker 
11181*7304104dSAndroid Build Coastguard Worker       int digits = 1;
11182*7304104dSAndroid Build Coastguard Worker       size_t offsets = (next_unitp - readp) / offset_size;
11183*7304104dSAndroid Build Coastguard Worker       while (offsets >= 10)
11184*7304104dSAndroid Build Coastguard Worker 	{
11185*7304104dSAndroid Build Coastguard Worker 	  ++digits;
11186*7304104dSAndroid Build Coastguard Worker 	  offsets /= 10;
11187*7304104dSAndroid Build Coastguard Worker 	}
11188*7304104dSAndroid Build Coastguard Worker 
11189*7304104dSAndroid Build Coastguard Worker       unsigned int uidx = 0;
11190*7304104dSAndroid Build Coastguard Worker       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
11191*7304104dSAndroid Build Coastguard Worker       printf (" Offsets start at 0x%zx:\n", index_offset);
11192*7304104dSAndroid Build Coastguard Worker       while (readp <= next_unitp - offset_size)
11193*7304104dSAndroid Build Coastguard Worker 	{
11194*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word offset;
11195*7304104dSAndroid Build Coastguard Worker 	  if (offset_size == 4)
11196*7304104dSAndroid Build Coastguard Worker 	    offset = read_4ubyte_unaligned_inc (dbg, readp);
11197*7304104dSAndroid Build Coastguard Worker 	  else
11198*7304104dSAndroid Build Coastguard Worker 	    offset = read_8ubyte_unaligned_inc (dbg, readp);
11199*7304104dSAndroid Build Coastguard Worker 	  const char *str = dwarf_getstring (dbg, offset, NULL);
11200*7304104dSAndroid Build Coastguard Worker 	  printf (" [%*u] [%*" PRIx64 "]  \"%s\"\n",
11201*7304104dSAndroid Build Coastguard Worker 		  digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
11202*7304104dSAndroid Build Coastguard Worker 	}
11203*7304104dSAndroid Build Coastguard Worker       printf ("\n");
11204*7304104dSAndroid Build Coastguard Worker 
11205*7304104dSAndroid Build Coastguard Worker       if (readp != next_unitp)
11206*7304104dSAndroid Build Coastguard Worker 	error (0, 0, "extra %zd bytes at end of unit",
11207*7304104dSAndroid Build Coastguard Worker 	       (size_t) (next_unitp - readp));
11208*7304104dSAndroid Build Coastguard Worker 
11209*7304104dSAndroid Build Coastguard Worker     next_unit:
11210*7304104dSAndroid Build Coastguard Worker       readp = next_unitp;
11211*7304104dSAndroid Build Coastguard Worker     }
11212*7304104dSAndroid Build Coastguard Worker }
11213*7304104dSAndroid Build Coastguard Worker 
11214*7304104dSAndroid Build Coastguard Worker 
11215*7304104dSAndroid Build Coastguard Worker /* Print the content of the call frame search table section
11216*7304104dSAndroid Build Coastguard Worker    '.eh_frame_hdr'.  */
11217*7304104dSAndroid Build Coastguard Worker static void
print_debug_frame_hdr_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)11218*7304104dSAndroid Build Coastguard Worker print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
11219*7304104dSAndroid Build Coastguard Worker 			       Ebl *ebl __attribute__ ((unused)),
11220*7304104dSAndroid Build Coastguard Worker 			       GElf_Ehdr *ehdr __attribute__ ((unused)),
11221*7304104dSAndroid Build Coastguard Worker 			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
11222*7304104dSAndroid Build Coastguard Worker {
11223*7304104dSAndroid Build Coastguard Worker   printf (_("\
11224*7304104dSAndroid Build Coastguard Worker \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
11225*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn));
11226*7304104dSAndroid Build Coastguard Worker 
11227*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_rawdata (scn, NULL);
11228*7304104dSAndroid Build Coastguard Worker 
11229*7304104dSAndroid Build Coastguard Worker   if (unlikely (data == NULL))
11230*7304104dSAndroid Build Coastguard Worker     {
11231*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get %s content: %s"),
11232*7304104dSAndroid Build Coastguard Worker 	     ".eh_frame_hdr", elf_errmsg (-1));
11233*7304104dSAndroid Build Coastguard Worker       return;
11234*7304104dSAndroid Build Coastguard Worker     }
11235*7304104dSAndroid Build Coastguard Worker 
11236*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = data->d_buf;
11237*7304104dSAndroid Build Coastguard Worker   const unsigned char *const dataend = ((unsigned char *) data->d_buf
11238*7304104dSAndroid Build Coastguard Worker 					+ data->d_size);
11239*7304104dSAndroid Build Coastguard Worker 
11240*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 4 > dataend))
11241*7304104dSAndroid Build Coastguard Worker     {
11242*7304104dSAndroid Build Coastguard Worker     invalid_data:
11243*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid data"));
11244*7304104dSAndroid Build Coastguard Worker       return;
11245*7304104dSAndroid Build Coastguard Worker     }
11246*7304104dSAndroid Build Coastguard Worker 
11247*7304104dSAndroid Build Coastguard Worker   unsigned int version = *readp++;
11248*7304104dSAndroid Build Coastguard Worker   unsigned int eh_frame_ptr_enc = *readp++;
11249*7304104dSAndroid Build Coastguard Worker   unsigned int fde_count_enc = *readp++;
11250*7304104dSAndroid Build Coastguard Worker   unsigned int table_enc = *readp++;
11251*7304104dSAndroid Build Coastguard Worker 
11252*7304104dSAndroid Build Coastguard Worker   printf (" version:          %u\n"
11253*7304104dSAndroid Build Coastguard Worker 	  " eh_frame_ptr_enc: %#x ",
11254*7304104dSAndroid Build Coastguard Worker 	  version, eh_frame_ptr_enc);
11255*7304104dSAndroid Build Coastguard Worker   print_encoding_base ("", eh_frame_ptr_enc);
11256*7304104dSAndroid Build Coastguard Worker   printf (" fde_count_enc:    %#x ", fde_count_enc);
11257*7304104dSAndroid Build Coastguard Worker   print_encoding_base ("", fde_count_enc);
11258*7304104dSAndroid Build Coastguard Worker   printf (" table_enc:        %#x ", table_enc);
11259*7304104dSAndroid Build Coastguard Worker   print_encoding_base ("", table_enc);
11260*7304104dSAndroid Build Coastguard Worker 
11261*7304104dSAndroid Build Coastguard Worker   uint64_t eh_frame_ptr = 0;
11262*7304104dSAndroid Build Coastguard Worker   if (eh_frame_ptr_enc != DW_EH_PE_omit)
11263*7304104dSAndroid Build Coastguard Worker     {
11264*7304104dSAndroid Build Coastguard Worker       readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
11265*7304104dSAndroid Build Coastguard Worker 			    dbg);
11266*7304104dSAndroid Build Coastguard Worker       if (unlikely (readp == NULL))
11267*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11268*7304104dSAndroid Build Coastguard Worker 
11269*7304104dSAndroid Build Coastguard Worker       printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
11270*7304104dSAndroid Build Coastguard Worker       if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
11271*7304104dSAndroid Build Coastguard Worker 	printf (" (offset: %#" PRIx64 ")",
11272*7304104dSAndroid Build Coastguard Worker 		/* +4 because of the 4 byte header of the section.  */
11273*7304104dSAndroid Build Coastguard Worker 		(uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
11274*7304104dSAndroid Build Coastguard Worker 
11275*7304104dSAndroid Build Coastguard Worker       putchar_unlocked ('\n');
11276*7304104dSAndroid Build Coastguard Worker     }
11277*7304104dSAndroid Build Coastguard Worker 
11278*7304104dSAndroid Build Coastguard Worker   uint64_t fde_count = 0;
11279*7304104dSAndroid Build Coastguard Worker   if (fde_count_enc != DW_EH_PE_omit)
11280*7304104dSAndroid Build Coastguard Worker     {
11281*7304104dSAndroid Build Coastguard Worker       readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
11282*7304104dSAndroid Build Coastguard Worker       if (unlikely (readp == NULL))
11283*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11284*7304104dSAndroid Build Coastguard Worker 
11285*7304104dSAndroid Build Coastguard Worker       printf (" fde_count:        %" PRIu64 "\n", fde_count);
11286*7304104dSAndroid Build Coastguard Worker     }
11287*7304104dSAndroid Build Coastguard Worker 
11288*7304104dSAndroid Build Coastguard Worker   if (fde_count == 0 || table_enc == DW_EH_PE_omit)
11289*7304104dSAndroid Build Coastguard Worker     return;
11290*7304104dSAndroid Build Coastguard Worker 
11291*7304104dSAndroid Build Coastguard Worker   puts (" Table:");
11292*7304104dSAndroid Build Coastguard Worker 
11293*7304104dSAndroid Build Coastguard Worker   /* Optimize for the most common case.  */
11294*7304104dSAndroid Build Coastguard Worker   if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
11295*7304104dSAndroid Build Coastguard Worker     while (fde_count > 0 && readp + 8 <= dataend)
11296*7304104dSAndroid Build Coastguard Worker       {
11297*7304104dSAndroid Build Coastguard Worker 	int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
11298*7304104dSAndroid Build Coastguard Worker 	uint64_t initial_offset = ((uint64_t) shdr->sh_offset
11299*7304104dSAndroid Build Coastguard Worker 				   + (int64_t) initial_location);
11300*7304104dSAndroid Build Coastguard Worker 	int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
11301*7304104dSAndroid Build Coastguard Worker 	// XXX Possibly print symbol name or section offset for initial_offset
11302*7304104dSAndroid Build Coastguard Worker 	printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
11303*7304104dSAndroid Build Coastguard Worker 		" fde=[%6" PRIx64 "]\n",
11304*7304104dSAndroid Build Coastguard Worker 		initial_location, initial_offset,
11305*7304104dSAndroid Build Coastguard Worker 		address, address - (eh_frame_ptr + 4));
11306*7304104dSAndroid Build Coastguard Worker       }
11307*7304104dSAndroid Build Coastguard Worker   else
11308*7304104dSAndroid Build Coastguard Worker     while (0 && readp < dataend)
11309*7304104dSAndroid Build Coastguard Worker       {
11310*7304104dSAndroid Build Coastguard Worker 
11311*7304104dSAndroid Build Coastguard Worker       }
11312*7304104dSAndroid Build Coastguard Worker }
11313*7304104dSAndroid Build Coastguard Worker 
11314*7304104dSAndroid Build Coastguard Worker 
11315*7304104dSAndroid Build Coastguard Worker /* Print the content of the exception handling table section
11316*7304104dSAndroid Build Coastguard Worker    '.eh_frame_hdr'.  */
11317*7304104dSAndroid Build Coastguard Worker static void
print_debug_exception_table(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)11318*7304104dSAndroid Build Coastguard Worker print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
11319*7304104dSAndroid Build Coastguard Worker 			     Ebl *ebl __attribute__ ((unused)),
11320*7304104dSAndroid Build Coastguard Worker 			     GElf_Ehdr *ehdr __attribute__ ((unused)),
11321*7304104dSAndroid Build Coastguard Worker 			     Elf_Scn *scn,
11322*7304104dSAndroid Build Coastguard Worker 			     GElf_Shdr *shdr __attribute__ ((unused)),
11323*7304104dSAndroid Build Coastguard Worker 			     Dwarf *dbg __attribute__ ((unused)))
11324*7304104dSAndroid Build Coastguard Worker {
11325*7304104dSAndroid Build Coastguard Worker   printf (_("\
11326*7304104dSAndroid Build Coastguard Worker \nException handling table section [%2zu] '.gcc_except_table':\n"),
11327*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn));
11328*7304104dSAndroid Build Coastguard Worker 
11329*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_rawdata (scn, NULL);
11330*7304104dSAndroid Build Coastguard Worker 
11331*7304104dSAndroid Build Coastguard Worker   if (unlikely (data == NULL))
11332*7304104dSAndroid Build Coastguard Worker     {
11333*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get %s content: %s"),
11334*7304104dSAndroid Build Coastguard Worker 	     ".gcc_except_table", elf_errmsg (-1));
11335*7304104dSAndroid Build Coastguard Worker       return;
11336*7304104dSAndroid Build Coastguard Worker     }
11337*7304104dSAndroid Build Coastguard Worker 
11338*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = data->d_buf;
11339*7304104dSAndroid Build Coastguard Worker   const unsigned char *const dataend = readp + data->d_size;
11340*7304104dSAndroid Build Coastguard Worker 
11341*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 1 > dataend))
11342*7304104dSAndroid Build Coastguard Worker     {
11343*7304104dSAndroid Build Coastguard Worker     invalid_data:
11344*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid data"));
11345*7304104dSAndroid Build Coastguard Worker       return;
11346*7304104dSAndroid Build Coastguard Worker     }
11347*7304104dSAndroid Build Coastguard Worker   unsigned int lpstart_encoding = *readp++;
11348*7304104dSAndroid Build Coastguard Worker   printf (_(" LPStart encoding:    %#x "), lpstart_encoding);
11349*7304104dSAndroid Build Coastguard Worker   print_encoding_base ("", lpstart_encoding);
11350*7304104dSAndroid Build Coastguard Worker   if (lpstart_encoding != DW_EH_PE_omit)
11351*7304104dSAndroid Build Coastguard Worker     {
11352*7304104dSAndroid Build Coastguard Worker       uint64_t lpstart;
11353*7304104dSAndroid Build Coastguard Worker       readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
11354*7304104dSAndroid Build Coastguard Worker       printf (" LPStart:             %#" PRIx64 "\n", lpstart);
11355*7304104dSAndroid Build Coastguard Worker     }
11356*7304104dSAndroid Build Coastguard Worker 
11357*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 1 > dataend))
11358*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11359*7304104dSAndroid Build Coastguard Worker   unsigned int ttype_encoding = *readp++;
11360*7304104dSAndroid Build Coastguard Worker   printf (_(" TType encoding:      %#x "), ttype_encoding);
11361*7304104dSAndroid Build Coastguard Worker   print_encoding_base ("", ttype_encoding);
11362*7304104dSAndroid Build Coastguard Worker   const unsigned char *ttype_base = NULL;
11363*7304104dSAndroid Build Coastguard Worker   if (ttype_encoding != DW_EH_PE_omit)
11364*7304104dSAndroid Build Coastguard Worker     {
11365*7304104dSAndroid Build Coastguard Worker       unsigned int ttype_base_offset;
11366*7304104dSAndroid Build Coastguard Worker       if (readp >= dataend)
11367*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11368*7304104dSAndroid Build Coastguard Worker       get_uleb128 (ttype_base_offset, readp, dataend);
11369*7304104dSAndroid Build Coastguard Worker       printf (" TType base offset:   %#x\n", ttype_base_offset);
11370*7304104dSAndroid Build Coastguard Worker       if ((size_t) (dataend - readp) > ttype_base_offset)
11371*7304104dSAndroid Build Coastguard Worker         ttype_base = readp + ttype_base_offset;
11372*7304104dSAndroid Build Coastguard Worker     }
11373*7304104dSAndroid Build Coastguard Worker 
11374*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 1 > dataend))
11375*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11376*7304104dSAndroid Build Coastguard Worker   unsigned int call_site_encoding = *readp++;
11377*7304104dSAndroid Build Coastguard Worker   printf (_(" Call site encoding:  %#x "), call_site_encoding);
11378*7304104dSAndroid Build Coastguard Worker   print_encoding_base ("", call_site_encoding);
11379*7304104dSAndroid Build Coastguard Worker   unsigned int call_site_table_len;
11380*7304104dSAndroid Build Coastguard Worker   if (readp >= dataend)
11381*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11382*7304104dSAndroid Build Coastguard Worker   get_uleb128 (call_site_table_len, readp, dataend);
11383*7304104dSAndroid Build Coastguard Worker 
11384*7304104dSAndroid Build Coastguard Worker   const unsigned char *const action_table = readp + call_site_table_len;
11385*7304104dSAndroid Build Coastguard Worker   if (unlikely (action_table > dataend))
11386*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11387*7304104dSAndroid Build Coastguard Worker   unsigned int u = 0;
11388*7304104dSAndroid Build Coastguard Worker   unsigned int max_action = 0;
11389*7304104dSAndroid Build Coastguard Worker   while (readp < action_table)
11390*7304104dSAndroid Build Coastguard Worker     {
11391*7304104dSAndroid Build Coastguard Worker       if (u == 0)
11392*7304104dSAndroid Build Coastguard Worker 	puts (_("\n Call site table:"));
11393*7304104dSAndroid Build Coastguard Worker 
11394*7304104dSAndroid Build Coastguard Worker       uint64_t call_site_start;
11395*7304104dSAndroid Build Coastguard Worker       readp = read_encoded (call_site_encoding, readp, dataend,
11396*7304104dSAndroid Build Coastguard Worker 			    &call_site_start, dbg);
11397*7304104dSAndroid Build Coastguard Worker       uint64_t call_site_length;
11398*7304104dSAndroid Build Coastguard Worker       readp = read_encoded (call_site_encoding, readp, dataend,
11399*7304104dSAndroid Build Coastguard Worker 			    &call_site_length, dbg);
11400*7304104dSAndroid Build Coastguard Worker       uint64_t landing_pad;
11401*7304104dSAndroid Build Coastguard Worker       readp = read_encoded (call_site_encoding, readp, dataend,
11402*7304104dSAndroid Build Coastguard Worker 			    &landing_pad, dbg);
11403*7304104dSAndroid Build Coastguard Worker       unsigned int action;
11404*7304104dSAndroid Build Coastguard Worker       if (readp >= dataend)
11405*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11406*7304104dSAndroid Build Coastguard Worker       get_uleb128 (action, readp, dataend);
11407*7304104dSAndroid Build Coastguard Worker       max_action = MAX (action, max_action);
11408*7304104dSAndroid Build Coastguard Worker       printf (_(" [%4u] Call site start:   %#" PRIx64 "\n"
11409*7304104dSAndroid Build Coastguard Worker 		       "        Call site length:  %" PRIu64 "\n"
11410*7304104dSAndroid Build Coastguard Worker 		       "        Landing pad:       %#" PRIx64 "\n"
11411*7304104dSAndroid Build Coastguard Worker 		       "        Action:            %u\n"),
11412*7304104dSAndroid Build Coastguard Worker 	      u++, call_site_start, call_site_length, landing_pad, action);
11413*7304104dSAndroid Build Coastguard Worker     }
11414*7304104dSAndroid Build Coastguard Worker   if (readp != action_table)
11415*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11416*7304104dSAndroid Build Coastguard Worker 
11417*7304104dSAndroid Build Coastguard Worker   unsigned int max_ar_filter = 0;
11418*7304104dSAndroid Build Coastguard Worker   if (max_action > 0)
11419*7304104dSAndroid Build Coastguard Worker     {
11420*7304104dSAndroid Build Coastguard Worker       puts ("\n Action table:");
11421*7304104dSAndroid Build Coastguard Worker 
11422*7304104dSAndroid Build Coastguard Worker       size_t maxdata = (size_t) (dataend - action_table);
11423*7304104dSAndroid Build Coastguard Worker       if (max_action > maxdata || maxdata - max_action < 1)
11424*7304104dSAndroid Build Coastguard Worker 	{
11425*7304104dSAndroid Build Coastguard Worker 	invalid_action_table:
11426*7304104dSAndroid Build Coastguard Worker 	  fputs (_("   <INVALID DATA>\n"), stdout);
11427*7304104dSAndroid Build Coastguard Worker 	  return;
11428*7304104dSAndroid Build Coastguard Worker 	}
11429*7304104dSAndroid Build Coastguard Worker 
11430*7304104dSAndroid Build Coastguard Worker       const unsigned char *const action_table_end
11431*7304104dSAndroid Build Coastguard Worker 	= action_table + max_action + 1;
11432*7304104dSAndroid Build Coastguard Worker 
11433*7304104dSAndroid Build Coastguard Worker       u = 0;
11434*7304104dSAndroid Build Coastguard Worker       do
11435*7304104dSAndroid Build Coastguard Worker 	{
11436*7304104dSAndroid Build Coastguard Worker 	  int ar_filter;
11437*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (ar_filter, readp, action_table_end);
11438*7304104dSAndroid Build Coastguard Worker 	  if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
11439*7304104dSAndroid Build Coastguard Worker 	    max_ar_filter = ar_filter;
11440*7304104dSAndroid Build Coastguard Worker 	  int ar_disp;
11441*7304104dSAndroid Build Coastguard Worker 	  if (readp >= action_table_end)
11442*7304104dSAndroid Build Coastguard Worker 	    goto invalid_action_table;
11443*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (ar_disp, readp, action_table_end);
11444*7304104dSAndroid Build Coastguard Worker 
11445*7304104dSAndroid Build Coastguard Worker 	  printf (" [%4u] ar_filter:  % d\n"
11446*7304104dSAndroid Build Coastguard Worker 		  "        ar_disp:    % -5d",
11447*7304104dSAndroid Build Coastguard Worker 		  u, ar_filter, ar_disp);
11448*7304104dSAndroid Build Coastguard Worker 	  if (abs (ar_disp) & 1)
11449*7304104dSAndroid Build Coastguard Worker 	    printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
11450*7304104dSAndroid Build Coastguard Worker 	  else if (ar_disp != 0)
11451*7304104dSAndroid Build Coastguard Worker 	    puts (" -> ???");
11452*7304104dSAndroid Build Coastguard Worker 	  else
11453*7304104dSAndroid Build Coastguard Worker 	    putchar_unlocked ('\n');
11454*7304104dSAndroid Build Coastguard Worker 	  ++u;
11455*7304104dSAndroid Build Coastguard Worker 	}
11456*7304104dSAndroid Build Coastguard Worker       while (readp < action_table_end);
11457*7304104dSAndroid Build Coastguard Worker     }
11458*7304104dSAndroid Build Coastguard Worker 
11459*7304104dSAndroid Build Coastguard Worker   if (max_ar_filter > 0 && ttype_base != NULL)
11460*7304104dSAndroid Build Coastguard Worker     {
11461*7304104dSAndroid Build Coastguard Worker       unsigned char dsize;
11462*7304104dSAndroid Build Coastguard Worker       puts ("\n TType table:");
11463*7304104dSAndroid Build Coastguard Worker 
11464*7304104dSAndroid Build Coastguard Worker       // XXX Not *4, size of encoding;
11465*7304104dSAndroid Build Coastguard Worker       switch (ttype_encoding & 7)
11466*7304104dSAndroid Build Coastguard Worker 	{
11467*7304104dSAndroid Build Coastguard Worker 	case DW_EH_PE_udata2:
11468*7304104dSAndroid Build Coastguard Worker 	case DW_EH_PE_sdata2:
11469*7304104dSAndroid Build Coastguard Worker 	  dsize = 2;
11470*7304104dSAndroid Build Coastguard Worker 	  break;
11471*7304104dSAndroid Build Coastguard Worker 	case DW_EH_PE_udata4:
11472*7304104dSAndroid Build Coastguard Worker 	case DW_EH_PE_sdata4:
11473*7304104dSAndroid Build Coastguard Worker 	  dsize = 4;
11474*7304104dSAndroid Build Coastguard Worker 	  break;
11475*7304104dSAndroid Build Coastguard Worker 	case DW_EH_PE_udata8:
11476*7304104dSAndroid Build Coastguard Worker 	case DW_EH_PE_sdata8:
11477*7304104dSAndroid Build Coastguard Worker 	  dsize = 8;
11478*7304104dSAndroid Build Coastguard Worker 	  break;
11479*7304104dSAndroid Build Coastguard Worker 	default:
11480*7304104dSAndroid Build Coastguard Worker 	  dsize = 0;
11481*7304104dSAndroid Build Coastguard Worker 	  error (1, 0, _("invalid TType encoding"));
11482*7304104dSAndroid Build Coastguard Worker 	}
11483*7304104dSAndroid Build Coastguard Worker 
11484*7304104dSAndroid Build Coastguard Worker       if (max_ar_filter
11485*7304104dSAndroid Build Coastguard Worker 	  > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
11486*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11487*7304104dSAndroid Build Coastguard Worker 
11488*7304104dSAndroid Build Coastguard Worker       readp = ttype_base - max_ar_filter * dsize;
11489*7304104dSAndroid Build Coastguard Worker       do
11490*7304104dSAndroid Build Coastguard Worker 	{
11491*7304104dSAndroid Build Coastguard Worker 	  uint64_t ttype;
11492*7304104dSAndroid Build Coastguard Worker 	  readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
11493*7304104dSAndroid Build Coastguard Worker 				dbg);
11494*7304104dSAndroid Build Coastguard Worker 	  printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
11495*7304104dSAndroid Build Coastguard Worker 	}
11496*7304104dSAndroid Build Coastguard Worker       while (readp < ttype_base);
11497*7304104dSAndroid Build Coastguard Worker     }
11498*7304104dSAndroid Build Coastguard Worker }
11499*7304104dSAndroid Build Coastguard Worker 
11500*7304104dSAndroid Build Coastguard Worker /* Print the content of the '.gdb_index' section.
11501*7304104dSAndroid Build Coastguard Worker    http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
11502*7304104dSAndroid Build Coastguard Worker */
11503*7304104dSAndroid Build Coastguard Worker static void
print_gdb_index_section(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr,Elf_Scn * scn,GElf_Shdr * shdr,Dwarf * dbg)11504*7304104dSAndroid Build Coastguard Worker print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
11505*7304104dSAndroid Build Coastguard Worker 			 GElf_Ehdr *ehdr __attribute__ ((unused)),
11506*7304104dSAndroid Build Coastguard Worker 			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
11507*7304104dSAndroid Build Coastguard Worker {
11508*7304104dSAndroid Build Coastguard Worker   printf (_("\nGDB section [%2zu] '%s' at offset %#" PRIx64
11509*7304104dSAndroid Build Coastguard Worker 		   " contains %" PRId64 " bytes :\n"),
11510*7304104dSAndroid Build Coastguard Worker 	  elf_ndxscn (scn), section_name (ebl, shdr),
11511*7304104dSAndroid Build Coastguard Worker 	  (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
11512*7304104dSAndroid Build Coastguard Worker 
11513*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_rawdata (scn, NULL);
11514*7304104dSAndroid Build Coastguard Worker 
11515*7304104dSAndroid Build Coastguard Worker   if (unlikely (data == NULL))
11516*7304104dSAndroid Build Coastguard Worker     {
11517*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("cannot get %s content: %s"),
11518*7304104dSAndroid Build Coastguard Worker 	     ".gdb_index", elf_errmsg (-1));
11519*7304104dSAndroid Build Coastguard Worker       return;
11520*7304104dSAndroid Build Coastguard Worker     }
11521*7304104dSAndroid Build Coastguard Worker 
11522*7304104dSAndroid Build Coastguard Worker   // .gdb_index is always in little endian.
11523*7304104dSAndroid Build Coastguard Worker   Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
11524*7304104dSAndroid Build Coastguard Worker   dbg = &dummy_dbg;
11525*7304104dSAndroid Build Coastguard Worker 
11526*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp = data->d_buf;
11527*7304104dSAndroid Build Coastguard Worker   const unsigned char *const dataend = readp + data->d_size;
11528*7304104dSAndroid Build Coastguard Worker 
11529*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 4 > dataend))
11530*7304104dSAndroid Build Coastguard Worker     {
11531*7304104dSAndroid Build Coastguard Worker     invalid_data:
11532*7304104dSAndroid Build Coastguard Worker       error (0, 0, _("invalid data"));
11533*7304104dSAndroid Build Coastguard Worker       return;
11534*7304104dSAndroid Build Coastguard Worker     }
11535*7304104dSAndroid Build Coastguard Worker 
11536*7304104dSAndroid Build Coastguard Worker   int32_t vers = read_4ubyte_unaligned (dbg, readp);
11537*7304104dSAndroid Build Coastguard Worker   printf (_(" Version:         %" PRId32 "\n"), vers);
11538*7304104dSAndroid Build Coastguard Worker 
11539*7304104dSAndroid Build Coastguard Worker   // The only difference between version 4 and version 5 is the
11540*7304104dSAndroid Build Coastguard Worker   // hash used for generating the table.  Version 6 contains symbols
11541*7304104dSAndroid Build Coastguard Worker   // for inlined functions, older versions didn't.  Version 7 adds
11542*7304104dSAndroid Build Coastguard Worker   // symbol kinds.  Version 8 just indicates that it correctly includes
11543*7304104dSAndroid Build Coastguard Worker   // TUs for symbols.  Version 9 adds shortcut table for information
11544*7304104dSAndroid Build Coastguard Worker   // regarding the main function.
11545*7304104dSAndroid Build Coastguard Worker   if (vers < 4 || vers > 9)
11546*7304104dSAndroid Build Coastguard Worker     {
11547*7304104dSAndroid Build Coastguard Worker       printf (_("  unknown version, cannot parse section\n"));
11548*7304104dSAndroid Build Coastguard Worker       return;
11549*7304104dSAndroid Build Coastguard Worker     }
11550*7304104dSAndroid Build Coastguard Worker 
11551*7304104dSAndroid Build Coastguard Worker   readp += 4;
11552*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 4 > dataend))
11553*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11554*7304104dSAndroid Build Coastguard Worker 
11555*7304104dSAndroid Build Coastguard Worker   uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
11556*7304104dSAndroid Build Coastguard Worker   printf (_(" CU offset:       %#" PRIx32 "\n"), cu_off);
11557*7304104dSAndroid Build Coastguard Worker 
11558*7304104dSAndroid Build Coastguard Worker   readp += 4;
11559*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 4 > dataend))
11560*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11561*7304104dSAndroid Build Coastguard Worker 
11562*7304104dSAndroid Build Coastguard Worker   uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
11563*7304104dSAndroid Build Coastguard Worker   printf (_(" TU offset:       %#" PRIx32 "\n"), tu_off);
11564*7304104dSAndroid Build Coastguard Worker 
11565*7304104dSAndroid Build Coastguard Worker   readp += 4;
11566*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 4 > dataend))
11567*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11568*7304104dSAndroid Build Coastguard Worker 
11569*7304104dSAndroid Build Coastguard Worker   uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
11570*7304104dSAndroid Build Coastguard Worker   printf (_(" address offset:  %#" PRIx32 "\n"), addr_off);
11571*7304104dSAndroid Build Coastguard Worker 
11572*7304104dSAndroid Build Coastguard Worker   readp += 4;
11573*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 4 > dataend))
11574*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11575*7304104dSAndroid Build Coastguard Worker 
11576*7304104dSAndroid Build Coastguard Worker   uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
11577*7304104dSAndroid Build Coastguard Worker   printf (_(" symbol offset:   %#" PRIx32 "\n"), sym_off);
11578*7304104dSAndroid Build Coastguard Worker 
11579*7304104dSAndroid Build Coastguard Worker   readp += 4;
11580*7304104dSAndroid Build Coastguard Worker   if (unlikely (readp + 4 > dataend))
11581*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11582*7304104dSAndroid Build Coastguard Worker 
11583*7304104dSAndroid Build Coastguard Worker   uint32_t shortcut_off = 0;
11584*7304104dSAndroid Build Coastguard Worker   if (vers >= 9)
11585*7304104dSAndroid Build Coastguard Worker     {
11586*7304104dSAndroid Build Coastguard Worker       shortcut_off = read_4ubyte_unaligned (dbg, readp);
11587*7304104dSAndroid Build Coastguard Worker       printf (_(" shortcut offset: %#" PRIx32 "\n"), shortcut_off);
11588*7304104dSAndroid Build Coastguard Worker 
11589*7304104dSAndroid Build Coastguard Worker       readp += 4;
11590*7304104dSAndroid Build Coastguard Worker       if (unlikely (readp + 4 > dataend))
11591*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11592*7304104dSAndroid Build Coastguard Worker     }
11593*7304104dSAndroid Build Coastguard Worker 
11594*7304104dSAndroid Build Coastguard Worker   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
11595*7304104dSAndroid Build Coastguard Worker   printf (_(" constant offset: %#" PRIx32 "\n"), const_off);
11596*7304104dSAndroid Build Coastguard Worker 
11597*7304104dSAndroid Build Coastguard Worker   if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
11598*7304104dSAndroid Build Coastguard Worker 		< const_off))
11599*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11600*7304104dSAndroid Build Coastguard Worker 
11601*7304104dSAndroid Build Coastguard Worker   readp = data->d_buf + cu_off;
11602*7304104dSAndroid Build Coastguard Worker 
11603*7304104dSAndroid Build Coastguard Worker   const unsigned char *nextp = data->d_buf + tu_off;
11604*7304104dSAndroid Build Coastguard Worker   if (tu_off >= data->d_size)
11605*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11606*7304104dSAndroid Build Coastguard Worker 
11607*7304104dSAndroid Build Coastguard Worker   size_t cu_nr = (nextp - readp) / 16;
11608*7304104dSAndroid Build Coastguard Worker 
11609*7304104dSAndroid Build Coastguard Worker   printf (_("\n CU list at offset %#" PRIx32
11610*7304104dSAndroid Build Coastguard Worker 		   " contains %zu entries:\n"),
11611*7304104dSAndroid Build Coastguard Worker 	  cu_off, cu_nr);
11612*7304104dSAndroid Build Coastguard Worker 
11613*7304104dSAndroid Build Coastguard Worker   size_t n = 0;
11614*7304104dSAndroid Build Coastguard Worker   while (dataend - readp >= 16 && n < cu_nr)
11615*7304104dSAndroid Build Coastguard Worker     {
11616*7304104dSAndroid Build Coastguard Worker       uint64_t off = read_8ubyte_unaligned (dbg, readp);
11617*7304104dSAndroid Build Coastguard Worker       readp += 8;
11618*7304104dSAndroid Build Coastguard Worker 
11619*7304104dSAndroid Build Coastguard Worker       uint64_t len = read_8ubyte_unaligned (dbg, readp);
11620*7304104dSAndroid Build Coastguard Worker       readp += 8;
11621*7304104dSAndroid Build Coastguard Worker 
11622*7304104dSAndroid Build Coastguard Worker       printf (" [%4zu] start: %0#8" PRIx64
11623*7304104dSAndroid Build Coastguard Worker 	      ", length: %5" PRIu64 "\n", n, off, len);
11624*7304104dSAndroid Build Coastguard Worker       n++;
11625*7304104dSAndroid Build Coastguard Worker     }
11626*7304104dSAndroid Build Coastguard Worker 
11627*7304104dSAndroid Build Coastguard Worker   readp = data->d_buf + tu_off;
11628*7304104dSAndroid Build Coastguard Worker   nextp = data->d_buf + addr_off;
11629*7304104dSAndroid Build Coastguard Worker   if (addr_off >= data->d_size)
11630*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11631*7304104dSAndroid Build Coastguard Worker 
11632*7304104dSAndroid Build Coastguard Worker   size_t tu_nr = (nextp - readp) / 24;
11633*7304104dSAndroid Build Coastguard Worker 
11634*7304104dSAndroid Build Coastguard Worker   printf (_("\n TU list at offset %#" PRIx32
11635*7304104dSAndroid Build Coastguard Worker 		   " contains %zu entries:\n"),
11636*7304104dSAndroid Build Coastguard Worker 	  tu_off, tu_nr);
11637*7304104dSAndroid Build Coastguard Worker 
11638*7304104dSAndroid Build Coastguard Worker   n = 0;
11639*7304104dSAndroid Build Coastguard Worker   while (dataend - readp >= 24 && n < tu_nr)
11640*7304104dSAndroid Build Coastguard Worker     {
11641*7304104dSAndroid Build Coastguard Worker       uint64_t off = read_8ubyte_unaligned (dbg, readp);
11642*7304104dSAndroid Build Coastguard Worker       readp += 8;
11643*7304104dSAndroid Build Coastguard Worker 
11644*7304104dSAndroid Build Coastguard Worker       uint64_t type = read_8ubyte_unaligned (dbg, readp);
11645*7304104dSAndroid Build Coastguard Worker       readp += 8;
11646*7304104dSAndroid Build Coastguard Worker 
11647*7304104dSAndroid Build Coastguard Worker       uint64_t sig = read_8ubyte_unaligned (dbg, readp);
11648*7304104dSAndroid Build Coastguard Worker       readp += 8;
11649*7304104dSAndroid Build Coastguard Worker 
11650*7304104dSAndroid Build Coastguard Worker       printf (" [%4zu] CU offset: %5" PRId64
11651*7304104dSAndroid Build Coastguard Worker 	      ", type offset: %5" PRId64
11652*7304104dSAndroid Build Coastguard Worker 	      ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
11653*7304104dSAndroid Build Coastguard Worker       n++;
11654*7304104dSAndroid Build Coastguard Worker     }
11655*7304104dSAndroid Build Coastguard Worker 
11656*7304104dSAndroid Build Coastguard Worker   readp = data->d_buf + addr_off;
11657*7304104dSAndroid Build Coastguard Worker   nextp = data->d_buf + sym_off;
11658*7304104dSAndroid Build Coastguard Worker   if (sym_off >= data->d_size)
11659*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11660*7304104dSAndroid Build Coastguard Worker 
11661*7304104dSAndroid Build Coastguard Worker   size_t addr_nr = (nextp - readp) / 20;
11662*7304104dSAndroid Build Coastguard Worker 
11663*7304104dSAndroid Build Coastguard Worker   printf (_("\n Address list at offset %#" PRIx32
11664*7304104dSAndroid Build Coastguard Worker 		   " contains %zu entries:\n"),
11665*7304104dSAndroid Build Coastguard Worker 	  addr_off, addr_nr);
11666*7304104dSAndroid Build Coastguard Worker 
11667*7304104dSAndroid Build Coastguard Worker   n = 0;
11668*7304104dSAndroid Build Coastguard Worker   while (dataend - readp >= 20 && n < addr_nr)
11669*7304104dSAndroid Build Coastguard Worker     {
11670*7304104dSAndroid Build Coastguard Worker       uint64_t low = read_8ubyte_unaligned (dbg, readp);
11671*7304104dSAndroid Build Coastguard Worker       readp += 8;
11672*7304104dSAndroid Build Coastguard Worker 
11673*7304104dSAndroid Build Coastguard Worker       uint64_t high = read_8ubyte_unaligned (dbg, readp);
11674*7304104dSAndroid Build Coastguard Worker       readp += 8;
11675*7304104dSAndroid Build Coastguard Worker 
11676*7304104dSAndroid Build Coastguard Worker       uint32_t idx = read_4ubyte_unaligned (dbg, readp);
11677*7304104dSAndroid Build Coastguard Worker       readp += 4;
11678*7304104dSAndroid Build Coastguard Worker 
11679*7304104dSAndroid Build Coastguard Worker       printf (" [%4zu] ", n);
11680*7304104dSAndroid Build Coastguard Worker       print_dwarf_addr (dwflmod, 8, low, low);
11681*7304104dSAndroid Build Coastguard Worker       printf ("..");
11682*7304104dSAndroid Build Coastguard Worker       print_dwarf_addr (dwflmod, 8, high - 1, high);
11683*7304104dSAndroid Build Coastguard Worker       printf (", CU index: %5" PRId32 "\n", idx);
11684*7304104dSAndroid Build Coastguard Worker       n++;
11685*7304104dSAndroid Build Coastguard Worker     }
11686*7304104dSAndroid Build Coastguard Worker 
11687*7304104dSAndroid Build Coastguard Worker   const unsigned char *const_start = data->d_buf + const_off;
11688*7304104dSAndroid Build Coastguard Worker   if (const_off >= data->d_size)
11689*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11690*7304104dSAndroid Build Coastguard Worker 
11691*7304104dSAndroid Build Coastguard Worker   const unsigned char *shortcut_start = NULL;
11692*7304104dSAndroid Build Coastguard Worker   if (vers >= 9)
11693*7304104dSAndroid Build Coastguard Worker     {
11694*7304104dSAndroid Build Coastguard Worker       if (shortcut_off >= data->d_size)
11695*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11696*7304104dSAndroid Build Coastguard Worker 
11697*7304104dSAndroid Build Coastguard Worker       shortcut_start = data->d_buf + shortcut_off;
11698*7304104dSAndroid Build Coastguard Worker       nextp = shortcut_start;
11699*7304104dSAndroid Build Coastguard Worker     }
11700*7304104dSAndroid Build Coastguard Worker   else
11701*7304104dSAndroid Build Coastguard Worker     nextp = const_start;
11702*7304104dSAndroid Build Coastguard Worker 
11703*7304104dSAndroid Build Coastguard Worker   readp = data->d_buf + sym_off;
11704*7304104dSAndroid Build Coastguard Worker   size_t sym_nr = (nextp - readp) / 8;
11705*7304104dSAndroid Build Coastguard Worker 
11706*7304104dSAndroid Build Coastguard Worker   printf (_("\n Symbol table at offset %#" PRIx32
11707*7304104dSAndroid Build Coastguard Worker 		   " contains %zu slots:\n"),
11708*7304104dSAndroid Build Coastguard Worker 	  addr_off, sym_nr);
11709*7304104dSAndroid Build Coastguard Worker 
11710*7304104dSAndroid Build Coastguard Worker   n = 0;
11711*7304104dSAndroid Build Coastguard Worker   while (dataend - readp >= 8 && n < sym_nr)
11712*7304104dSAndroid Build Coastguard Worker     {
11713*7304104dSAndroid Build Coastguard Worker       uint32_t name = read_4ubyte_unaligned (dbg, readp);
11714*7304104dSAndroid Build Coastguard Worker       readp += 4;
11715*7304104dSAndroid Build Coastguard Worker 
11716*7304104dSAndroid Build Coastguard Worker       uint32_t vector = read_4ubyte_unaligned (dbg, readp);
11717*7304104dSAndroid Build Coastguard Worker       readp += 4;
11718*7304104dSAndroid Build Coastguard Worker 
11719*7304104dSAndroid Build Coastguard Worker       if (name != 0 || vector != 0)
11720*7304104dSAndroid Build Coastguard Worker 	{
11721*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *sym = const_start + name;
11722*7304104dSAndroid Build Coastguard Worker 	  if (unlikely ((size_t) (dataend - const_start) < name
11723*7304104dSAndroid Build Coastguard Worker 			|| memchr (sym, '\0', dataend - sym) == NULL))
11724*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
11725*7304104dSAndroid Build Coastguard Worker 
11726*7304104dSAndroid Build Coastguard Worker 	  printf (" [%4zu] symbol: %s, CUs: ", n, sym);
11727*7304104dSAndroid Build Coastguard Worker 
11728*7304104dSAndroid Build Coastguard Worker 	  const unsigned char *readcus = const_start + vector;
11729*7304104dSAndroid Build Coastguard Worker 	  if (unlikely ((size_t) (dataend - const_start) < vector))
11730*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
11731*7304104dSAndroid Build Coastguard Worker 	  uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
11732*7304104dSAndroid Build Coastguard Worker 	  while (cus--)
11733*7304104dSAndroid Build Coastguard Worker 	    {
11734*7304104dSAndroid Build Coastguard Worker 	      uint32_t cu_kind, cu, kind;
11735*7304104dSAndroid Build Coastguard Worker 	      bool is_static;
11736*7304104dSAndroid Build Coastguard Worker 	      readcus += 4;
11737*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (readcus + 4 > dataend))
11738*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
11739*7304104dSAndroid Build Coastguard Worker 	      cu_kind = read_4ubyte_unaligned (dbg, readcus);
11740*7304104dSAndroid Build Coastguard Worker 	      cu = cu_kind & ((1 << 24) - 1);
11741*7304104dSAndroid Build Coastguard Worker 	      kind = (cu_kind >> 28) & 7;
11742*7304104dSAndroid Build Coastguard Worker 	      is_static = cu_kind & (1U << 31);
11743*7304104dSAndroid Build Coastguard Worker 	      if (cu > cu_nr - 1)
11744*7304104dSAndroid Build Coastguard Worker 		printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
11745*7304104dSAndroid Build Coastguard Worker 	      else
11746*7304104dSAndroid Build Coastguard Worker 		printf ("%" PRId32, cu);
11747*7304104dSAndroid Build Coastguard Worker 	      if (kind != 0)
11748*7304104dSAndroid Build Coastguard Worker 		{
11749*7304104dSAndroid Build Coastguard Worker 		  printf (" (");
11750*7304104dSAndroid Build Coastguard Worker 		  switch (kind)
11751*7304104dSAndroid Build Coastguard Worker 		    {
11752*7304104dSAndroid Build Coastguard Worker 		    case 1:
11753*7304104dSAndroid Build Coastguard Worker 		      printf ("type");
11754*7304104dSAndroid Build Coastguard Worker 		      break;
11755*7304104dSAndroid Build Coastguard Worker 		    case 2:
11756*7304104dSAndroid Build Coastguard Worker 		      printf ("var");
11757*7304104dSAndroid Build Coastguard Worker 		      break;
11758*7304104dSAndroid Build Coastguard Worker 		    case 3:
11759*7304104dSAndroid Build Coastguard Worker 		      printf ("func");
11760*7304104dSAndroid Build Coastguard Worker 		      break;
11761*7304104dSAndroid Build Coastguard Worker 		    case 4:
11762*7304104dSAndroid Build Coastguard Worker 		      printf ("other");
11763*7304104dSAndroid Build Coastguard Worker 		      break;
11764*7304104dSAndroid Build Coastguard Worker 		    default:
11765*7304104dSAndroid Build Coastguard Worker 		      printf ("unknown-0x%" PRIx32, kind);
11766*7304104dSAndroid Build Coastguard Worker 		      break;
11767*7304104dSAndroid Build Coastguard Worker 		    }
11768*7304104dSAndroid Build Coastguard Worker 		  printf (":%c)", (is_static ? 'S' : 'G'));
11769*7304104dSAndroid Build Coastguard Worker 		}
11770*7304104dSAndroid Build Coastguard Worker 	      if (cus > 0)
11771*7304104dSAndroid Build Coastguard Worker 		printf (", ");
11772*7304104dSAndroid Build Coastguard Worker 	    }
11773*7304104dSAndroid Build Coastguard Worker 	  printf ("\n");
11774*7304104dSAndroid Build Coastguard Worker 	}
11775*7304104dSAndroid Build Coastguard Worker       n++;
11776*7304104dSAndroid Build Coastguard Worker     }
11777*7304104dSAndroid Build Coastguard Worker 
11778*7304104dSAndroid Build Coastguard Worker   if (vers < 9)
11779*7304104dSAndroid Build Coastguard Worker     return;
11780*7304104dSAndroid Build Coastguard Worker 
11781*7304104dSAndroid Build Coastguard Worker   if (unlikely (shortcut_start == NULL))
11782*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11783*7304104dSAndroid Build Coastguard Worker 
11784*7304104dSAndroid Build Coastguard Worker   readp = shortcut_start;
11785*7304104dSAndroid Build Coastguard Worker   nextp = const_start;
11786*7304104dSAndroid Build Coastguard Worker   size_t shortcut_nr = (nextp - readp) / 4;
11787*7304104dSAndroid Build Coastguard Worker 
11788*7304104dSAndroid Build Coastguard Worker   if (unlikely (shortcut_nr != 2))
11789*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
11790*7304104dSAndroid Build Coastguard Worker 
11791*7304104dSAndroid Build Coastguard Worker   printf (_("\nShortcut table at offset %#" PRIx32 " contains %zu slots:\n"),
11792*7304104dSAndroid Build Coastguard Worker 	  shortcut_off, shortcut_nr);
11793*7304104dSAndroid Build Coastguard Worker 
11794*7304104dSAndroid Build Coastguard Worker   uint32_t lang = read_4ubyte_unaligned (dbg, readp);
11795*7304104dSAndroid Build Coastguard Worker   readp += 4;
11796*7304104dSAndroid Build Coastguard Worker 
11797*7304104dSAndroid Build Coastguard Worker   /* Include the hex number of LANG in the output if the language
11798*7304104dSAndroid Build Coastguard Worker      is unknown.  */
11799*7304104dSAndroid Build Coastguard Worker   const char *lang_str = dwarf_lang_string (lang);
11800*7304104dSAndroid Build Coastguard Worker   lang_str = string_or_unknown (lang_str, lang, DW_LANG_lo_user,
11801*7304104dSAndroid Build Coastguard Worker 				DW_LANG_hi_user, true);
11802*7304104dSAndroid Build Coastguard Worker 
11803*7304104dSAndroid Build Coastguard Worker   printf (_("Language of main: %s\n"), lang_str);
11804*7304104dSAndroid Build Coastguard Worker   printf (_("Name of main: "));
11805*7304104dSAndroid Build Coastguard Worker 
11806*7304104dSAndroid Build Coastguard Worker   if (lang != 0)
11807*7304104dSAndroid Build Coastguard Worker     {
11808*7304104dSAndroid Build Coastguard Worker       uint32_t name = read_4ubyte_unaligned (dbg, readp);
11809*7304104dSAndroid Build Coastguard Worker       readp += 4;
11810*7304104dSAndroid Build Coastguard Worker       const unsigned char *sym = const_start + name;
11811*7304104dSAndroid Build Coastguard Worker 
11812*7304104dSAndroid Build Coastguard Worker       if (unlikely ((size_t) (dataend - const_start) < name
11813*7304104dSAndroid Build Coastguard Worker 		    || memchr (sym, '\0', dataend - sym) == NULL))
11814*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
11815*7304104dSAndroid Build Coastguard Worker 
11816*7304104dSAndroid Build Coastguard Worker       printf ("%s\n", sym);
11817*7304104dSAndroid Build Coastguard Worker     }
11818*7304104dSAndroid Build Coastguard Worker   else
11819*7304104dSAndroid Build Coastguard Worker     printf ("<unknown>\n");
11820*7304104dSAndroid Build Coastguard Worker }
11821*7304104dSAndroid Build Coastguard Worker 
11822*7304104dSAndroid Build Coastguard Worker /* Returns true and sets split DWARF CU id if there is a split compile
11823*7304104dSAndroid Build Coastguard Worker    unit in the given Dwarf, and no non-split units are found (before it).  */
11824*7304104dSAndroid Build Coastguard Worker static bool
is_split_dwarf(Dwarf * dbg,uint64_t * id,Dwarf_CU ** split_cu)11825*7304104dSAndroid Build Coastguard Worker is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu)
11826*7304104dSAndroid Build Coastguard Worker {
11827*7304104dSAndroid Build Coastguard Worker   Dwarf_CU *cu = NULL;
11828*7304104dSAndroid Build Coastguard Worker   while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
11829*7304104dSAndroid Build Coastguard Worker     {
11830*7304104dSAndroid Build Coastguard Worker       uint8_t unit_type;
11831*7304104dSAndroid Build Coastguard Worker       if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
11832*7304104dSAndroid Build Coastguard Worker 			 id, NULL, NULL) != 0)
11833*7304104dSAndroid Build Coastguard Worker 	return false;
11834*7304104dSAndroid Build Coastguard Worker 
11835*7304104dSAndroid Build Coastguard Worker       if (unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
11836*7304104dSAndroid Build Coastguard Worker 	return false;
11837*7304104dSAndroid Build Coastguard Worker 
11838*7304104dSAndroid Build Coastguard Worker       /* We really only care about the split compile unit, the types
11839*7304104dSAndroid Build Coastguard Worker 	 should be fine and self sufficient.  Also they don't have an
11840*7304104dSAndroid Build Coastguard Worker 	 id that we can match with a skeleton unit.  */
11841*7304104dSAndroid Build Coastguard Worker       if (unit_type == DW_UT_split_compile)
11842*7304104dSAndroid Build Coastguard Worker 	{
11843*7304104dSAndroid Build Coastguard Worker 	  *split_cu = cu;
11844*7304104dSAndroid Build Coastguard Worker 	  return true;
11845*7304104dSAndroid Build Coastguard Worker 	}
11846*7304104dSAndroid Build Coastguard Worker     }
11847*7304104dSAndroid Build Coastguard Worker 
11848*7304104dSAndroid Build Coastguard Worker   return false;
11849*7304104dSAndroid Build Coastguard Worker }
11850*7304104dSAndroid Build Coastguard Worker 
11851*7304104dSAndroid Build Coastguard Worker /* Check that there is one and only one Dwfl_Module, return in arg.  */
11852*7304104dSAndroid Build Coastguard Worker static int
getone_dwflmod(Dwfl_Module * dwflmod,void ** userdata,const char * name,Dwarf_Addr base,void * arg)11853*7304104dSAndroid Build Coastguard Worker getone_dwflmod (Dwfl_Module *dwflmod,
11854*7304104dSAndroid Build Coastguard Worker 	       void **userdata __attribute__ ((unused)),
11855*7304104dSAndroid Build Coastguard Worker 	       const char *name __attribute__ ((unused)),
11856*7304104dSAndroid Build Coastguard Worker 	       Dwarf_Addr base __attribute__ ((unused)),
11857*7304104dSAndroid Build Coastguard Worker 	       void *arg)
11858*7304104dSAndroid Build Coastguard Worker {
11859*7304104dSAndroid Build Coastguard Worker   Dwfl_Module **m = (Dwfl_Module **) arg;
11860*7304104dSAndroid Build Coastguard Worker   if (*m != NULL)
11861*7304104dSAndroid Build Coastguard Worker     return DWARF_CB_ABORT;
11862*7304104dSAndroid Build Coastguard Worker   *m = dwflmod;
11863*7304104dSAndroid Build Coastguard Worker   return DWARF_CB_OK;
11864*7304104dSAndroid Build Coastguard Worker }
11865*7304104dSAndroid Build Coastguard Worker 
11866*7304104dSAndroid Build Coastguard Worker static void
print_debug(Dwfl_Module * dwflmod,Ebl * ebl,GElf_Ehdr * ehdr)11867*7304104dSAndroid Build Coastguard Worker print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
11868*7304104dSAndroid Build Coastguard Worker {
11869*7304104dSAndroid Build Coastguard Worker   /* Used for skeleton file, if necessary for split DWARF.  */
11870*7304104dSAndroid Build Coastguard Worker   Dwfl *skel_dwfl = NULL;
11871*7304104dSAndroid Build Coastguard Worker   Dwfl_Module *skel_mod = NULL;
11872*7304104dSAndroid Build Coastguard Worker   char *skel_name = NULL;
11873*7304104dSAndroid Build Coastguard Worker   Dwarf *split_dbg = NULL;
11874*7304104dSAndroid Build Coastguard Worker   Dwarf_CU *split_cu = NULL;
11875*7304104dSAndroid Build Coastguard Worker 
11876*7304104dSAndroid Build Coastguard Worker   /* Before we start the real work get a debug context descriptor.  */
11877*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr dwbias;
11878*7304104dSAndroid Build Coastguard Worker   Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
11879*7304104dSAndroid Build Coastguard Worker   Dwarf dummy_dbg =
11880*7304104dSAndroid Build Coastguard Worker     {
11881*7304104dSAndroid Build Coastguard Worker       .elf = ebl->elf,
11882*7304104dSAndroid Build Coastguard Worker       .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
11883*7304104dSAndroid Build Coastguard Worker     };
11884*7304104dSAndroid Build Coastguard Worker   if (dbg == NULL)
11885*7304104dSAndroid Build Coastguard Worker     {
11886*7304104dSAndroid Build Coastguard Worker       if ((print_debug_sections & ~(section_exception|section_frame)) != 0)
11887*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("cannot get debug context descriptor: %s"),
11888*7304104dSAndroid Build Coastguard Worker 	       dwfl_errmsg (-1));
11889*7304104dSAndroid Build Coastguard Worker       dbg = &dummy_dbg;
11890*7304104dSAndroid Build Coastguard Worker     }
11891*7304104dSAndroid Build Coastguard Worker   else
11892*7304104dSAndroid Build Coastguard Worker     {
11893*7304104dSAndroid Build Coastguard Worker       /* If we are asked about a split dwarf (.dwo) file, use the user
11894*7304104dSAndroid Build Coastguard Worker 	 provided, or find the corresponding skeleton file. If we got
11895*7304104dSAndroid Build Coastguard Worker 	 a skeleton file, replace the given dwflmod and dbg, with one
11896*7304104dSAndroid Build Coastguard Worker 	 derived from the skeleton file to provide enough context.  */
11897*7304104dSAndroid Build Coastguard Worker       uint64_t split_id;
11898*7304104dSAndroid Build Coastguard Worker       if (is_split_dwarf (dbg, &split_id, &split_cu))
11899*7304104dSAndroid Build Coastguard Worker 	{
11900*7304104dSAndroid Build Coastguard Worker 	  if (dwarf_skeleton != NULL)
11901*7304104dSAndroid Build Coastguard Worker 	    skel_name = strdup (dwarf_skeleton);
11902*7304104dSAndroid Build Coastguard Worker 	  else
11903*7304104dSAndroid Build Coastguard Worker 	    {
11904*7304104dSAndroid Build Coastguard Worker 	      /* Replace file.dwo with file.o and see if that matches. */
11905*7304104dSAndroid Build Coastguard Worker 	      const char *fname;
11906*7304104dSAndroid Build Coastguard Worker 	      dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL,
11907*7304104dSAndroid Build Coastguard Worker 				&fname, NULL);
11908*7304104dSAndroid Build Coastguard Worker 	      if (fname != NULL)
11909*7304104dSAndroid Build Coastguard Worker 		{
11910*7304104dSAndroid Build Coastguard Worker 		  size_t flen = strlen (fname);
11911*7304104dSAndroid Build Coastguard Worker 		  if (flen > 4 && strcmp (".dwo", fname + flen - 4) == 0)
11912*7304104dSAndroid Build Coastguard Worker 		    {
11913*7304104dSAndroid Build Coastguard Worker 		      skel_name = strdup (fname);
11914*7304104dSAndroid Build Coastguard Worker 		      if (skel_name != NULL)
11915*7304104dSAndroid Build Coastguard Worker 			{
11916*7304104dSAndroid Build Coastguard Worker 			  skel_name[flen - 3] = 'o';
11917*7304104dSAndroid Build Coastguard Worker 			  skel_name[flen - 2] = '\0';
11918*7304104dSAndroid Build Coastguard Worker 			}
11919*7304104dSAndroid Build Coastguard Worker 		    }
11920*7304104dSAndroid Build Coastguard Worker 		}
11921*7304104dSAndroid Build Coastguard Worker 	    }
11922*7304104dSAndroid Build Coastguard Worker 
11923*7304104dSAndroid Build Coastguard Worker 	  if (skel_name != NULL)
11924*7304104dSAndroid Build Coastguard Worker 	    {
11925*7304104dSAndroid Build Coastguard Worker 	      int skel_fd = open (skel_name, O_RDONLY);
11926*7304104dSAndroid Build Coastguard Worker 	      if (skel_fd == -1)
11927*7304104dSAndroid Build Coastguard Worker 		fprintf (stderr, "Warning: Couldn't open DWARF skeleton file"
11928*7304104dSAndroid Build Coastguard Worker 			 " '%s'\n", skel_name);
11929*7304104dSAndroid Build Coastguard Worker 	      else
11930*7304104dSAndroid Build Coastguard Worker 		skel_dwfl = create_dwfl (skel_fd, skel_name);
11931*7304104dSAndroid Build Coastguard Worker 
11932*7304104dSAndroid Build Coastguard Worker 	      if (skel_dwfl != NULL)
11933*7304104dSAndroid Build Coastguard Worker 		{
11934*7304104dSAndroid Build Coastguard Worker 		  if (dwfl_getmodules (skel_dwfl, &getone_dwflmod,
11935*7304104dSAndroid Build Coastguard Worker 				       &skel_mod, 0) != 0)
11936*7304104dSAndroid Build Coastguard Worker 		    {
11937*7304104dSAndroid Build Coastguard Worker 		      fprintf (stderr, "Warning: Bad DWARF skeleton,"
11938*7304104dSAndroid Build Coastguard Worker 			       " multiple modules '%s'\n", skel_name);
11939*7304104dSAndroid Build Coastguard Worker 		      dwfl_end (skel_dwfl);
11940*7304104dSAndroid Build Coastguard Worker 		      skel_mod = NULL;
11941*7304104dSAndroid Build Coastguard Worker 		    }
11942*7304104dSAndroid Build Coastguard Worker 		}
11943*7304104dSAndroid Build Coastguard Worker 	      else if (skel_fd != -1)
11944*7304104dSAndroid Build Coastguard Worker 		fprintf (stderr, "Warning: Couldn't create skeleton dwfl for"
11945*7304104dSAndroid Build Coastguard Worker 			 " '%s': %s\n", skel_name, dwfl_errmsg (-1));
11946*7304104dSAndroid Build Coastguard Worker 
11947*7304104dSAndroid Build Coastguard Worker 	      if (skel_mod != NULL)
11948*7304104dSAndroid Build Coastguard Worker 		{
11949*7304104dSAndroid Build Coastguard Worker 		  Dwarf *skel_dbg = dwfl_module_getdwarf (skel_mod, &dwbias);
11950*7304104dSAndroid Build Coastguard Worker 		  if (skel_dbg != NULL)
11951*7304104dSAndroid Build Coastguard Worker 		    {
11952*7304104dSAndroid Build Coastguard Worker 		      /* First check the skeleton CU DIE, only fetch
11953*7304104dSAndroid Build Coastguard Worker 			 the split DIE if we know the id matches to
11954*7304104dSAndroid Build Coastguard Worker 			 not unnecessary search for any split DIEs we
11955*7304104dSAndroid Build Coastguard Worker 			 don't need. */
11956*7304104dSAndroid Build Coastguard Worker 		      Dwarf_CU *cu = NULL;
11957*7304104dSAndroid Build Coastguard Worker 		      while (dwarf_get_units (skel_dbg, cu, &cu,
11958*7304104dSAndroid Build Coastguard Worker 					      NULL, NULL, NULL, NULL) == 0)
11959*7304104dSAndroid Build Coastguard Worker 			{
11960*7304104dSAndroid Build Coastguard Worker 			  uint8_t unit_type;
11961*7304104dSAndroid Build Coastguard Worker 			  uint64_t skel_id;
11962*7304104dSAndroid Build Coastguard Worker 			  if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
11963*7304104dSAndroid Build Coastguard Worker 					     &skel_id, NULL, NULL) == 0
11964*7304104dSAndroid Build Coastguard Worker 			      && unit_type == DW_UT_skeleton
11965*7304104dSAndroid Build Coastguard Worker 			      && split_id == skel_id)
11966*7304104dSAndroid Build Coastguard Worker 			    {
11967*7304104dSAndroid Build Coastguard Worker 			      Dwarf_Die subdie;
11968*7304104dSAndroid Build Coastguard Worker 			      if (dwarf_cu_info (cu, NULL, NULL, NULL,
11969*7304104dSAndroid Build Coastguard Worker 						 &subdie,
11970*7304104dSAndroid Build Coastguard Worker 						 NULL, NULL, NULL) == 0
11971*7304104dSAndroid Build Coastguard Worker 				  && dwarf_tag (&subdie) != DW_TAG_invalid)
11972*7304104dSAndroid Build Coastguard Worker 				{
11973*7304104dSAndroid Build Coastguard Worker 				  split_dbg = dwarf_cu_getdwarf (subdie.cu);
11974*7304104dSAndroid Build Coastguard Worker 				  if (split_dbg == NULL)
11975*7304104dSAndroid Build Coastguard Worker 				    fprintf (stderr,
11976*7304104dSAndroid Build Coastguard Worker 					     "Warning: Couldn't get split_dbg:"
11977*7304104dSAndroid Build Coastguard Worker 					     " %s\n", dwarf_errmsg (-1));
11978*7304104dSAndroid Build Coastguard Worker 				  break;
11979*7304104dSAndroid Build Coastguard Worker 				}
11980*7304104dSAndroid Build Coastguard Worker 			      else
11981*7304104dSAndroid Build Coastguard Worker 				{
11982*7304104dSAndroid Build Coastguard Worker 				  /* Everything matches up, but not
11983*7304104dSAndroid Build Coastguard Worker 				     according to libdw. Which means
11984*7304104dSAndroid Build Coastguard Worker 				     the user knew better.  So...
11985*7304104dSAndroid Build Coastguard Worker 				     Terrible hack... We can never
11986*7304104dSAndroid Build Coastguard Worker 				     destroy the underlying dwfl
11987*7304104dSAndroid Build Coastguard Worker 				     because it would free the wrong
11988*7304104dSAndroid Build Coastguard Worker 				     Dwarfs... So we leak memory...*/
11989*7304104dSAndroid Build Coastguard Worker 				  if (cu->split == NULL
11990*7304104dSAndroid Build Coastguard Worker 				      && dwarf_skeleton != NULL)
11991*7304104dSAndroid Build Coastguard Worker 				    {
11992*7304104dSAndroid Build Coastguard Worker 				      do_not_close_dwfl = true;
11993*7304104dSAndroid Build Coastguard Worker 				      __libdw_link_skel_split (cu, split_cu);
11994*7304104dSAndroid Build Coastguard Worker 				      split_dbg = dwarf_cu_getdwarf (split_cu);
11995*7304104dSAndroid Build Coastguard Worker 				      break;
11996*7304104dSAndroid Build Coastguard Worker 				    }
11997*7304104dSAndroid Build Coastguard Worker 				  else
11998*7304104dSAndroid Build Coastguard Worker 				    fprintf (stderr, "Warning: Couldn't get"
11999*7304104dSAndroid Build Coastguard Worker 					     " skeleton subdie: %s\n",
12000*7304104dSAndroid Build Coastguard Worker 					     dwarf_errmsg (-1));
12001*7304104dSAndroid Build Coastguard Worker 				}
12002*7304104dSAndroid Build Coastguard Worker 			    }
12003*7304104dSAndroid Build Coastguard Worker 			}
12004*7304104dSAndroid Build Coastguard Worker 		      if (split_dbg == NULL)
12005*7304104dSAndroid Build Coastguard Worker 			fprintf (stderr, "Warning: '%s' didn't contain a skeleton for split id %" PRIx64 "\n", skel_name, split_id);
12006*7304104dSAndroid Build Coastguard Worker 		    }
12007*7304104dSAndroid Build Coastguard Worker 		  else
12008*7304104dSAndroid Build Coastguard Worker 		    fprintf (stderr, "Warning: Couldn't get skeleton DWARF:"
12009*7304104dSAndroid Build Coastguard Worker 			     " %s\n", dwfl_errmsg (-1));
12010*7304104dSAndroid Build Coastguard Worker 		}
12011*7304104dSAndroid Build Coastguard Worker 	    }
12012*7304104dSAndroid Build Coastguard Worker 
12013*7304104dSAndroid Build Coastguard Worker 	  if (split_dbg != NULL)
12014*7304104dSAndroid Build Coastguard Worker 	    {
12015*7304104dSAndroid Build Coastguard Worker 	      dbg = split_dbg;
12016*7304104dSAndroid Build Coastguard Worker 	      dwflmod = skel_mod;
12017*7304104dSAndroid Build Coastguard Worker 	    }
12018*7304104dSAndroid Build Coastguard Worker 	  else if (skel_name == NULL)
12019*7304104dSAndroid Build Coastguard Worker 	    fprintf (stderr,
12020*7304104dSAndroid Build Coastguard Worker 		     "Warning: split DWARF file, but no skeleton found.\n");
12021*7304104dSAndroid Build Coastguard Worker 	}
12022*7304104dSAndroid Build Coastguard Worker       else if (dwarf_skeleton != NULL)
12023*7304104dSAndroid Build Coastguard Worker 	fprintf (stderr, "Warning: DWARF skeleton given,"
12024*7304104dSAndroid Build Coastguard Worker 		 " but not a split DWARF file\n");
12025*7304104dSAndroid Build Coastguard Worker     }
12026*7304104dSAndroid Build Coastguard Worker 
12027*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
12028*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
12029*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
12030*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
12031*7304104dSAndroid Build Coastguard Worker 
12032*7304104dSAndroid Build Coastguard Worker   /* If the .debug_info section is listed as implicitly required then
12033*7304104dSAndroid Build Coastguard Worker      we must make sure to handle it before handling any other debug
12034*7304104dSAndroid Build Coastguard Worker      section.  Various other sections depend on the CU DIEs being
12035*7304104dSAndroid Build Coastguard Worker      scanned (silently) first.  */
12036*7304104dSAndroid Build Coastguard Worker   bool implicit_info = (implicit_debug_sections & section_info) != 0;
12037*7304104dSAndroid Build Coastguard Worker   bool explicit_info = (print_debug_sections & section_info) != 0;
12038*7304104dSAndroid Build Coastguard Worker   if (implicit_info)
12039*7304104dSAndroid Build Coastguard Worker     {
12040*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn = NULL;
12041*7304104dSAndroid Build Coastguard Worker       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
12042*7304104dSAndroid Build Coastguard Worker 	{
12043*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr shdr_mem;
12044*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
12045*7304104dSAndroid Build Coastguard Worker 
12046*7304104dSAndroid Build Coastguard Worker 	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
12047*7304104dSAndroid Build Coastguard Worker 	    {
12048*7304104dSAndroid Build Coastguard Worker 	      const char *name = elf_strptr (ebl->elf, shstrndx,
12049*7304104dSAndroid Build Coastguard Worker 					     shdr->sh_name);
12050*7304104dSAndroid Build Coastguard Worker 	      if (name == NULL)
12051*7304104dSAndroid Build Coastguard Worker 		continue;
12052*7304104dSAndroid Build Coastguard Worker 
12053*7304104dSAndroid Build Coastguard Worker 	      if (strcmp (name, ".debug_info") == 0
12054*7304104dSAndroid Build Coastguard Worker 		  || strcmp (name, ".debug_info.dwo") == 0
12055*7304104dSAndroid Build Coastguard Worker 		  || strcmp (name, ".zdebug_info") == 0
12056*7304104dSAndroid Build Coastguard Worker 		  || strcmp (name, ".zdebug_info.dwo") == 0
12057*7304104dSAndroid Build Coastguard Worker 		  || strcmp (name, ".gnu.debuglto_.debug_info") == 0)
12058*7304104dSAndroid Build Coastguard Worker 		{
12059*7304104dSAndroid Build Coastguard Worker 		  print_debug_info_section (dwflmod, ebl, ehdr,
12060*7304104dSAndroid Build Coastguard Worker 					    scn, shdr, dbg);
12061*7304104dSAndroid Build Coastguard Worker 		  break;
12062*7304104dSAndroid Build Coastguard Worker 		}
12063*7304104dSAndroid Build Coastguard Worker 	    }
12064*7304104dSAndroid Build Coastguard Worker 	}
12065*7304104dSAndroid Build Coastguard Worker       print_debug_sections &= ~section_info;
12066*7304104dSAndroid Build Coastguard Worker       implicit_debug_sections &= ~section_info;
12067*7304104dSAndroid Build Coastguard Worker     }
12068*7304104dSAndroid Build Coastguard Worker 
12069*7304104dSAndroid Build Coastguard Worker   /* Look through all the sections for the debugging sections to print.  */
12070*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
12071*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
12072*7304104dSAndroid Build Coastguard Worker     {
12073*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
12074*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
12075*7304104dSAndroid Build Coastguard Worker 
12076*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
12077*7304104dSAndroid Build Coastguard Worker 	{
12078*7304104dSAndroid Build Coastguard Worker 	  static const struct
12079*7304104dSAndroid Build Coastguard Worker 	  {
12080*7304104dSAndroid Build Coastguard Worker 	    const char *name;
12081*7304104dSAndroid Build Coastguard Worker 	    enum section_e bitmask;
12082*7304104dSAndroid Build Coastguard Worker 	    void (*fp) (Dwfl_Module *, Ebl *,
12083*7304104dSAndroid Build Coastguard Worker 			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
12084*7304104dSAndroid Build Coastguard Worker 	  } debug_sections[] =
12085*7304104dSAndroid Build Coastguard Worker 	    {
12086*7304104dSAndroid Build Coastguard Worker #define NEW_SECTION(name) \
12087*7304104dSAndroid Build Coastguard Worker 	      { ".debug_" #name, section_##name, print_debug_##name##_section }
12088*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (abbrev),
12089*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (addr),
12090*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (aranges),
12091*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (frame),
12092*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (info),
12093*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (types),
12094*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (line),
12095*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (loc),
12096*7304104dSAndroid Build Coastguard Worker 	      /* loclists is loc for DWARF5.  */
12097*7304104dSAndroid Build Coastguard Worker 	      { ".debug_loclists", section_loc,
12098*7304104dSAndroid Build Coastguard Worker 		print_debug_loclists_section },
12099*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (pubnames),
12100*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (str),
12101*7304104dSAndroid Build Coastguard Worker 	      /* A DWARF5 specialised debug string section.  */
12102*7304104dSAndroid Build Coastguard Worker 	      { ".debug_line_str", section_str,
12103*7304104dSAndroid Build Coastguard Worker 		print_debug_str_section },
12104*7304104dSAndroid Build Coastguard Worker 	      /* DWARF5 string offsets table.  */
12105*7304104dSAndroid Build Coastguard Worker 	      { ".debug_str_offsets", section_str,
12106*7304104dSAndroid Build Coastguard Worker 		print_debug_str_offsets_section },
12107*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (macinfo),
12108*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (macro),
12109*7304104dSAndroid Build Coastguard Worker 	      NEW_SECTION (ranges),
12110*7304104dSAndroid Build Coastguard Worker 	      /* rnglists is ranges for DWARF5.  */
12111*7304104dSAndroid Build Coastguard Worker 	      { ".debug_rnglists", section_ranges,
12112*7304104dSAndroid Build Coastguard Worker 		print_debug_rnglists_section },
12113*7304104dSAndroid Build Coastguard Worker 	      { ".eh_frame", section_frame | section_exception,
12114*7304104dSAndroid Build Coastguard Worker 		print_debug_frame_section },
12115*7304104dSAndroid Build Coastguard Worker 	      { ".eh_frame_hdr", section_frame | section_exception,
12116*7304104dSAndroid Build Coastguard Worker 		print_debug_frame_hdr_section },
12117*7304104dSAndroid Build Coastguard Worker 	      { ".gcc_except_table", section_frame | section_exception,
12118*7304104dSAndroid Build Coastguard Worker 		print_debug_exception_table },
12119*7304104dSAndroid Build Coastguard Worker 	      { ".gdb_index", section_gdb_index, print_gdb_index_section }
12120*7304104dSAndroid Build Coastguard Worker 	    };
12121*7304104dSAndroid Build Coastguard Worker 	  const int ndebug_sections = (sizeof (debug_sections)
12122*7304104dSAndroid Build Coastguard Worker 				       / sizeof (debug_sections[0]));
12123*7304104dSAndroid Build Coastguard Worker 	  const char *name = elf_strptr (ebl->elf, shstrndx,
12124*7304104dSAndroid Build Coastguard Worker 					 shdr->sh_name);
12125*7304104dSAndroid Build Coastguard Worker 	  if (name == NULL)
12126*7304104dSAndroid Build Coastguard Worker 	    continue;
12127*7304104dSAndroid Build Coastguard Worker 
12128*7304104dSAndroid Build Coastguard Worker 	  int n;
12129*7304104dSAndroid Build Coastguard Worker 	  for (n = 0; n < ndebug_sections; ++n)
12130*7304104dSAndroid Build Coastguard Worker 	    {
12131*7304104dSAndroid Build Coastguard Worker 	      size_t dbglen = strlen (debug_sections[n].name);
12132*7304104dSAndroid Build Coastguard Worker 	      size_t scnlen = strlen (name);
12133*7304104dSAndroid Build Coastguard Worker 	      if ((strncmp (name, debug_sections[n].name, dbglen) == 0
12134*7304104dSAndroid Build Coastguard Worker 		   && (dbglen == scnlen
12135*7304104dSAndroid Build Coastguard Worker 		       || (scnlen == dbglen + 4
12136*7304104dSAndroid Build Coastguard Worker 			   && strstr (name, ".dwo") == name + dbglen)))
12137*7304104dSAndroid Build Coastguard Worker 		  || (name[0] == '.' && name[1] == 'z'
12138*7304104dSAndroid Build Coastguard Worker 		      && debug_sections[n].name[1] == 'd'
12139*7304104dSAndroid Build Coastguard Worker 		      && strncmp (&name[2], &debug_sections[n].name[1],
12140*7304104dSAndroid Build Coastguard Worker 				  dbglen - 1) == 0
12141*7304104dSAndroid Build Coastguard Worker 		      && (scnlen == dbglen + 1
12142*7304104dSAndroid Build Coastguard Worker 			  || (scnlen == dbglen + 5
12143*7304104dSAndroid Build Coastguard Worker 			      && strstr (name, ".dwo") == name + dbglen + 1)))
12144*7304104dSAndroid Build Coastguard Worker 		  || (scnlen > 14 /* .gnu.debuglto_ prefix. */
12145*7304104dSAndroid Build Coastguard Worker 		      && startswith (name, ".gnu.debuglto_")
12146*7304104dSAndroid Build Coastguard Worker 		      && strcmp (&name[14], debug_sections[n].name) == 0)
12147*7304104dSAndroid Build Coastguard Worker )
12148*7304104dSAndroid Build Coastguard Worker 		{
12149*7304104dSAndroid Build Coastguard Worker 		  if ((print_debug_sections | implicit_debug_sections)
12150*7304104dSAndroid Build Coastguard Worker 		      & debug_sections[n].bitmask)
12151*7304104dSAndroid Build Coastguard Worker 		    debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
12152*7304104dSAndroid Build Coastguard Worker 		  break;
12153*7304104dSAndroid Build Coastguard Worker 		}
12154*7304104dSAndroid Build Coastguard Worker 	    }
12155*7304104dSAndroid Build Coastguard Worker 	}
12156*7304104dSAndroid Build Coastguard Worker     }
12157*7304104dSAndroid Build Coastguard Worker 
12158*7304104dSAndroid Build Coastguard Worker   dwfl_end (skel_dwfl);
12159*7304104dSAndroid Build Coastguard Worker   free (skel_name);
12160*7304104dSAndroid Build Coastguard Worker 
12161*7304104dSAndroid Build Coastguard Worker   /* Turn implicit and/or explicit back on in case we go over another file.  */
12162*7304104dSAndroid Build Coastguard Worker   if (implicit_info)
12163*7304104dSAndroid Build Coastguard Worker     implicit_debug_sections |= section_info;
12164*7304104dSAndroid Build Coastguard Worker   if (explicit_info)
12165*7304104dSAndroid Build Coastguard Worker     print_debug_sections |= section_info;
12166*7304104dSAndroid Build Coastguard Worker 
12167*7304104dSAndroid Build Coastguard Worker   reset_listptr (&known_locsptr);
12168*7304104dSAndroid Build Coastguard Worker   reset_listptr (&known_loclistsptr);
12169*7304104dSAndroid Build Coastguard Worker   reset_listptr (&known_rangelistptr);
12170*7304104dSAndroid Build Coastguard Worker   reset_listptr (&known_rnglistptr);
12171*7304104dSAndroid Build Coastguard Worker   reset_listptr (&known_addrbases);
12172*7304104dSAndroid Build Coastguard Worker   reset_listptr (&known_stroffbases);
12173*7304104dSAndroid Build Coastguard Worker }
12174*7304104dSAndroid Build Coastguard Worker 
12175*7304104dSAndroid Build Coastguard Worker 
12176*7304104dSAndroid Build Coastguard Worker #define ITEM_INDENT		4
12177*7304104dSAndroid Build Coastguard Worker #define WRAP_COLUMN		75
12178*7304104dSAndroid Build Coastguard Worker 
12179*7304104dSAndroid Build Coastguard Worker /* Print "NAME: FORMAT", wrapping when output text would make the line
12180*7304104dSAndroid Build Coastguard Worker    exceed WRAP_COLUMN.  Unpadded numbers look better for the core items
12181*7304104dSAndroid Build Coastguard Worker    but this function is also used for registers which should be printed
12182*7304104dSAndroid Build Coastguard Worker    aligned.  Fortunately registers output uses fixed fields width (such
12183*7304104dSAndroid Build Coastguard Worker    as %11d) for the alignment.
12184*7304104dSAndroid Build Coastguard Worker 
12185*7304104dSAndroid Build Coastguard Worker    Line breaks should not depend on the particular values although that
12186*7304104dSAndroid Build Coastguard Worker    may happen in some cases of the core items.  */
12187*7304104dSAndroid Build Coastguard Worker 
12188*7304104dSAndroid Build Coastguard Worker static unsigned int
12189*7304104dSAndroid Build Coastguard Worker __attribute__ ((format (printf, 6, 7)))
print_core_item(unsigned int colno,char sep,unsigned int wrap,size_t name_width,const char * name,const char * format,...)12190*7304104dSAndroid Build Coastguard Worker print_core_item (unsigned int colno, char sep, unsigned int wrap,
12191*7304104dSAndroid Build Coastguard Worker 		 size_t name_width, const char *name, const char *format, ...)
12192*7304104dSAndroid Build Coastguard Worker {
12193*7304104dSAndroid Build Coastguard Worker   size_t len = strlen (name);
12194*7304104dSAndroid Build Coastguard Worker   if (name_width < len)
12195*7304104dSAndroid Build Coastguard Worker     name_width = len;
12196*7304104dSAndroid Build Coastguard Worker 
12197*7304104dSAndroid Build Coastguard Worker   char *out;
12198*7304104dSAndroid Build Coastguard Worker   va_list ap;
12199*7304104dSAndroid Build Coastguard Worker   va_start (ap, format);
12200*7304104dSAndroid Build Coastguard Worker   int out_len = vasprintf (&out, format, ap);
12201*7304104dSAndroid Build Coastguard Worker   va_end (ap);
12202*7304104dSAndroid Build Coastguard Worker   if (out_len == -1)
12203*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("memory exhausted"));
12204*7304104dSAndroid Build Coastguard Worker 
12205*7304104dSAndroid Build Coastguard Worker   size_t n = name_width + sizeof ": " - 1 + out_len;
12206*7304104dSAndroid Build Coastguard Worker 
12207*7304104dSAndroid Build Coastguard Worker   if (colno == 0)
12208*7304104dSAndroid Build Coastguard Worker     {
12209*7304104dSAndroid Build Coastguard Worker       printf ("%*s", ITEM_INDENT, "");
12210*7304104dSAndroid Build Coastguard Worker       colno = ITEM_INDENT + n;
12211*7304104dSAndroid Build Coastguard Worker     }
12212*7304104dSAndroid Build Coastguard Worker   else if (colno + 2 + n < wrap)
12213*7304104dSAndroid Build Coastguard Worker     {
12214*7304104dSAndroid Build Coastguard Worker       printf ("%c ", sep);
12215*7304104dSAndroid Build Coastguard Worker       colno += 2 + n;
12216*7304104dSAndroid Build Coastguard Worker     }
12217*7304104dSAndroid Build Coastguard Worker   else
12218*7304104dSAndroid Build Coastguard Worker     {
12219*7304104dSAndroid Build Coastguard Worker       printf ("\n%*s", ITEM_INDENT, "");
12220*7304104dSAndroid Build Coastguard Worker       colno = ITEM_INDENT + n;
12221*7304104dSAndroid Build Coastguard Worker     }
12222*7304104dSAndroid Build Coastguard Worker 
12223*7304104dSAndroid Build Coastguard Worker   printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
12224*7304104dSAndroid Build Coastguard Worker 
12225*7304104dSAndroid Build Coastguard Worker   free (out);
12226*7304104dSAndroid Build Coastguard Worker 
12227*7304104dSAndroid Build Coastguard Worker   return colno;
12228*7304104dSAndroid Build Coastguard Worker }
12229*7304104dSAndroid Build Coastguard Worker 
12230*7304104dSAndroid Build Coastguard Worker static const void *
convert(Elf * core,Elf_Type type,uint_fast16_t count,void * value,const void * data,size_t size)12231*7304104dSAndroid Build Coastguard Worker convert (Elf *core, Elf_Type type, uint_fast16_t count,
12232*7304104dSAndroid Build Coastguard Worker 	 void *value, const void *data, size_t size)
12233*7304104dSAndroid Build Coastguard Worker {
12234*7304104dSAndroid Build Coastguard Worker   Elf_Data valuedata =
12235*7304104dSAndroid Build Coastguard Worker     {
12236*7304104dSAndroid Build Coastguard Worker       .d_type = type,
12237*7304104dSAndroid Build Coastguard Worker       .d_buf = value,
12238*7304104dSAndroid Build Coastguard Worker       .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
12239*7304104dSAndroid Build Coastguard Worker       .d_version = EV_CURRENT,
12240*7304104dSAndroid Build Coastguard Worker     };
12241*7304104dSAndroid Build Coastguard Worker   Elf_Data indata =
12242*7304104dSAndroid Build Coastguard Worker     {
12243*7304104dSAndroid Build Coastguard Worker       .d_type = type,
12244*7304104dSAndroid Build Coastguard Worker       .d_buf = (void *) data,
12245*7304104dSAndroid Build Coastguard Worker       .d_size = valuedata.d_size,
12246*7304104dSAndroid Build Coastguard Worker       .d_version = EV_CURRENT,
12247*7304104dSAndroid Build Coastguard Worker     };
12248*7304104dSAndroid Build Coastguard Worker 
12249*7304104dSAndroid Build Coastguard Worker   Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
12250*7304104dSAndroid Build Coastguard Worker 		 ? elf32_xlatetom : elf64_xlatetom)
12251*7304104dSAndroid Build Coastguard Worker     (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
12252*7304104dSAndroid Build Coastguard Worker   if (d == NULL)
12253*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot convert core note data: %s"),
12254*7304104dSAndroid Build Coastguard Worker 		elf_errmsg (-1));
12255*7304104dSAndroid Build Coastguard Worker 
12256*7304104dSAndroid Build Coastguard Worker   return data + indata.d_size;
12257*7304104dSAndroid Build Coastguard Worker }
12258*7304104dSAndroid Build Coastguard Worker 
12259*7304104dSAndroid Build Coastguard Worker typedef uint8_t GElf_Byte;
12260*7304104dSAndroid Build Coastguard Worker 
12261*7304104dSAndroid Build Coastguard Worker static unsigned int
handle_core_item(Elf * core,const Ebl_Core_Item * item,const void * desc,unsigned int colno,size_t * repeated_size)12262*7304104dSAndroid Build Coastguard Worker handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
12263*7304104dSAndroid Build Coastguard Worker 		  unsigned int colno, size_t *repeated_size)
12264*7304104dSAndroid Build Coastguard Worker {
12265*7304104dSAndroid Build Coastguard Worker   uint_fast16_t count = item->count ?: 1;
12266*7304104dSAndroid Build Coastguard Worker   /* Ebl_Core_Item count is always a small number.
12267*7304104dSAndroid Build Coastguard Worker      Make sure the backend didn't put in some large bogus value.  */
12268*7304104dSAndroid Build Coastguard Worker   assert (count < 128);
12269*7304104dSAndroid Build Coastguard Worker 
12270*7304104dSAndroid Build Coastguard Worker #define TYPES								      \
12271*7304104dSAndroid Build Coastguard Worker   DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8);			      \
12272*7304104dSAndroid Build Coastguard Worker   DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16);			      \
12273*7304104dSAndroid Build Coastguard Worker   DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32);			      \
12274*7304104dSAndroid Build Coastguard Worker   DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32);			      \
12275*7304104dSAndroid Build Coastguard Worker   DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64);			      \
12276*7304104dSAndroid Build Coastguard Worker   DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
12277*7304104dSAndroid Build Coastguard Worker 
12278*7304104dSAndroid Build Coastguard Worker #define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
12279*7304104dSAndroid Build Coastguard Worker   typedef union { TYPES; } value_t;
12280*7304104dSAndroid Build Coastguard Worker   void *data = alloca (count * sizeof (value_t));
12281*7304104dSAndroid Build Coastguard Worker #undef DO_TYPE
12282*7304104dSAndroid Build Coastguard Worker 
12283*7304104dSAndroid Build Coastguard Worker #define DO_TYPE(NAME, Name, hex, dec) \
12284*7304104dSAndroid Build Coastguard Worker     GElf_##Name *value_##Name __attribute__((unused)) = data
12285*7304104dSAndroid Build Coastguard Worker   TYPES;
12286*7304104dSAndroid Build Coastguard Worker #undef DO_TYPE
12287*7304104dSAndroid Build Coastguard Worker 
12288*7304104dSAndroid Build Coastguard Worker   size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
12289*7304104dSAndroid Build Coastguard Worker   size_t convsize = size;
12290*7304104dSAndroid Build Coastguard Worker   if (repeated_size != NULL)
12291*7304104dSAndroid Build Coastguard Worker     {
12292*7304104dSAndroid Build Coastguard Worker       if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
12293*7304104dSAndroid Build Coastguard Worker 	{
12294*7304104dSAndroid Build Coastguard Worker 	  data = alloca (*repeated_size);
12295*7304104dSAndroid Build Coastguard Worker 	  count *= *repeated_size / size;
12296*7304104dSAndroid Build Coastguard Worker 	  convsize = count * size;
12297*7304104dSAndroid Build Coastguard Worker 	  *repeated_size -= convsize;
12298*7304104dSAndroid Build Coastguard Worker 	}
12299*7304104dSAndroid Build Coastguard Worker       else if (item->count != 0 || item->format != '\n')
12300*7304104dSAndroid Build Coastguard Worker 	*repeated_size -= size;
12301*7304104dSAndroid Build Coastguard Worker     }
12302*7304104dSAndroid Build Coastguard Worker 
12303*7304104dSAndroid Build Coastguard Worker   convert (core, item->type, count, data, desc + item->offset, convsize);
12304*7304104dSAndroid Build Coastguard Worker 
12305*7304104dSAndroid Build Coastguard Worker   Elf_Type type = item->type;
12306*7304104dSAndroid Build Coastguard Worker   if (type == ELF_T_ADDR)
12307*7304104dSAndroid Build Coastguard Worker     type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
12308*7304104dSAndroid Build Coastguard Worker 
12309*7304104dSAndroid Build Coastguard Worker   switch (item->format)
12310*7304104dSAndroid Build Coastguard Worker     {
12311*7304104dSAndroid Build Coastguard Worker     case 'd':
12312*7304104dSAndroid Build Coastguard Worker       assert (count == 1);
12313*7304104dSAndroid Build Coastguard Worker       switch (type)
12314*7304104dSAndroid Build Coastguard Worker 	{
12315*7304104dSAndroid Build Coastguard Worker #define DO_TYPE(NAME, Name, hex, dec)					      \
12316*7304104dSAndroid Build Coastguard Worker 	  case ELF_T_##NAME:						      \
12317*7304104dSAndroid Build Coastguard Worker 	    colno = print_core_item (colno, ',', WRAP_COLUMN,		      \
12318*7304104dSAndroid Build Coastguard Worker 				     0, item->name, dec, value_##Name[0]); \
12319*7304104dSAndroid Build Coastguard Worker 	    break
12320*7304104dSAndroid Build Coastguard Worker 	  TYPES;
12321*7304104dSAndroid Build Coastguard Worker #undef DO_TYPE
12322*7304104dSAndroid Build Coastguard Worker 	default:
12323*7304104dSAndroid Build Coastguard Worker 	  abort ();
12324*7304104dSAndroid Build Coastguard Worker 	}
12325*7304104dSAndroid Build Coastguard Worker       break;
12326*7304104dSAndroid Build Coastguard Worker 
12327*7304104dSAndroid Build Coastguard Worker     case 'x':
12328*7304104dSAndroid Build Coastguard Worker       assert (count == 1);
12329*7304104dSAndroid Build Coastguard Worker       switch (type)
12330*7304104dSAndroid Build Coastguard Worker 	{
12331*7304104dSAndroid Build Coastguard Worker #define DO_TYPE(NAME, Name, hex, dec)					      \
12332*7304104dSAndroid Build Coastguard Worker 	  case ELF_T_##NAME:						      \
12333*7304104dSAndroid Build Coastguard Worker 	    colno = print_core_item (colno, ',', WRAP_COLUMN,		      \
12334*7304104dSAndroid Build Coastguard Worker 				     0, item->name, hex, value_##Name[0]);      \
12335*7304104dSAndroid Build Coastguard Worker 	    break
12336*7304104dSAndroid Build Coastguard Worker 	  TYPES;
12337*7304104dSAndroid Build Coastguard Worker #undef DO_TYPE
12338*7304104dSAndroid Build Coastguard Worker 	default:
12339*7304104dSAndroid Build Coastguard Worker 	  abort ();
12340*7304104dSAndroid Build Coastguard Worker 	}
12341*7304104dSAndroid Build Coastguard Worker       break;
12342*7304104dSAndroid Build Coastguard Worker 
12343*7304104dSAndroid Build Coastguard Worker     case 'b':
12344*7304104dSAndroid Build Coastguard Worker     case 'B':
12345*7304104dSAndroid Build Coastguard Worker       assert (size % sizeof (unsigned int) == 0);
12346*7304104dSAndroid Build Coastguard Worker       unsigned int nbits = count * size * 8;
12347*7304104dSAndroid Build Coastguard Worker       unsigned int pop = 0;
12348*7304104dSAndroid Build Coastguard Worker       for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
12349*7304104dSAndroid Build Coastguard Worker 	pop += __builtin_popcount (*i);
12350*7304104dSAndroid Build Coastguard Worker       bool negate = pop > nbits / 2;
12351*7304104dSAndroid Build Coastguard Worker       const unsigned int bias = item->format == 'b';
12352*7304104dSAndroid Build Coastguard Worker 
12353*7304104dSAndroid Build Coastguard Worker       {
12354*7304104dSAndroid Build Coastguard Worker 	char printed[(negate ? nbits - pop : pop) * 16 + 1];
12355*7304104dSAndroid Build Coastguard Worker 	char *p = printed;
12356*7304104dSAndroid Build Coastguard Worker 	*p = '\0';
12357*7304104dSAndroid Build Coastguard Worker 
12358*7304104dSAndroid Build Coastguard Worker 	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
12359*7304104dSAndroid Build Coastguard Worker 	  {
12360*7304104dSAndroid Build Coastguard Worker 	    assert (size == sizeof (unsigned int) * 2);
12361*7304104dSAndroid Build Coastguard Worker 	    for (unsigned int *i = data;
12362*7304104dSAndroid Build Coastguard Worker 		 (void *) i < data + count * size; i += 2)
12363*7304104dSAndroid Build Coastguard Worker 	      {
12364*7304104dSAndroid Build Coastguard Worker 		unsigned int w = i[1];
12365*7304104dSAndroid Build Coastguard Worker 		i[1] = i[0];
12366*7304104dSAndroid Build Coastguard Worker 		i[0] = w;
12367*7304104dSAndroid Build Coastguard Worker 	      }
12368*7304104dSAndroid Build Coastguard Worker 	  }
12369*7304104dSAndroid Build Coastguard Worker 
12370*7304104dSAndroid Build Coastguard Worker 	unsigned int lastbit = 0;
12371*7304104dSAndroid Build Coastguard Worker 	unsigned int run = 0;
12372*7304104dSAndroid Build Coastguard Worker 	for (const unsigned int *i = data;
12373*7304104dSAndroid Build Coastguard Worker 	     (void *) i < data + count * size; ++i)
12374*7304104dSAndroid Build Coastguard Worker 	  {
12375*7304104dSAndroid Build Coastguard Worker 	    unsigned int bit = ((void *) i - data) * 8;
12376*7304104dSAndroid Build Coastguard Worker 	    unsigned int w = negate ? ~*i : *i;
12377*7304104dSAndroid Build Coastguard Worker 	    while (w != 0)
12378*7304104dSAndroid Build Coastguard Worker 	      {
12379*7304104dSAndroid Build Coastguard Worker 		/* Note that a right shift equal to (or greater than)
12380*7304104dSAndroid Build Coastguard Worker 		   the number of bits of w is undefined behaviour.  In
12381*7304104dSAndroid Build Coastguard Worker 		   particular when the least significant bit is bit 32
12382*7304104dSAndroid Build Coastguard Worker 		   (w = 0x8000000) then w >>= n is undefined.  So
12383*7304104dSAndroid Build Coastguard Worker 		   explicitly handle that case separately.  */
12384*7304104dSAndroid Build Coastguard Worker 		unsigned int n = ffs (w);
12385*7304104dSAndroid Build Coastguard Worker 		if (n < sizeof (w) * 8)
12386*7304104dSAndroid Build Coastguard Worker 		  w >>= n;
12387*7304104dSAndroid Build Coastguard Worker 		else
12388*7304104dSAndroid Build Coastguard Worker 		  w = 0;
12389*7304104dSAndroid Build Coastguard Worker 		bit += n;
12390*7304104dSAndroid Build Coastguard Worker 
12391*7304104dSAndroid Build Coastguard Worker 		if (lastbit != 0 && lastbit + 1 == bit)
12392*7304104dSAndroid Build Coastguard Worker 		  ++run;
12393*7304104dSAndroid Build Coastguard Worker 		else
12394*7304104dSAndroid Build Coastguard Worker 		  {
12395*7304104dSAndroid Build Coastguard Worker 		    if (lastbit == 0)
12396*7304104dSAndroid Build Coastguard Worker 		      p += sprintf (p, "%u", bit - bias);
12397*7304104dSAndroid Build Coastguard Worker 		    else if (run == 0)
12398*7304104dSAndroid Build Coastguard Worker 		      p += sprintf (p, ",%u", bit - bias);
12399*7304104dSAndroid Build Coastguard Worker 		    else
12400*7304104dSAndroid Build Coastguard Worker 		      p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
12401*7304104dSAndroid Build Coastguard Worker 		    run = 0;
12402*7304104dSAndroid Build Coastguard Worker 		  }
12403*7304104dSAndroid Build Coastguard Worker 
12404*7304104dSAndroid Build Coastguard Worker 		lastbit = bit;
12405*7304104dSAndroid Build Coastguard Worker 	      }
12406*7304104dSAndroid Build Coastguard Worker 	  }
12407*7304104dSAndroid Build Coastguard Worker 	if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
12408*7304104dSAndroid Build Coastguard Worker 	  p += sprintf (p, "-%u", lastbit - bias);
12409*7304104dSAndroid Build Coastguard Worker 
12410*7304104dSAndroid Build Coastguard Worker 	colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
12411*7304104dSAndroid Build Coastguard Worker 				 negate ? "~<%s>" : "<%s>", printed);
12412*7304104dSAndroid Build Coastguard Worker       }
12413*7304104dSAndroid Build Coastguard Worker       break;
12414*7304104dSAndroid Build Coastguard Worker 
12415*7304104dSAndroid Build Coastguard Worker     case 'T':
12416*7304104dSAndroid Build Coastguard Worker     case (char) ('T'|0x80):
12417*7304104dSAndroid Build Coastguard Worker       assert (count == 2);
12418*7304104dSAndroid Build Coastguard Worker       Dwarf_Word sec;
12419*7304104dSAndroid Build Coastguard Worker       Dwarf_Word usec;
12420*7304104dSAndroid Build Coastguard Worker       switch (type)
12421*7304104dSAndroid Build Coastguard Worker 	{
12422*7304104dSAndroid Build Coastguard Worker #define DO_TYPE(NAME, Name, hex, dec)					      \
12423*7304104dSAndroid Build Coastguard Worker 	  case ELF_T_##NAME:						      \
12424*7304104dSAndroid Build Coastguard Worker 	    sec = value_##Name[0];					      \
12425*7304104dSAndroid Build Coastguard Worker 	    usec = value_##Name[1];					      \
12426*7304104dSAndroid Build Coastguard Worker 	    break
12427*7304104dSAndroid Build Coastguard Worker 	  TYPES;
12428*7304104dSAndroid Build Coastguard Worker #undef DO_TYPE
12429*7304104dSAndroid Build Coastguard Worker 	default:
12430*7304104dSAndroid Build Coastguard Worker 	  abort ();
12431*7304104dSAndroid Build Coastguard Worker 	}
12432*7304104dSAndroid Build Coastguard Worker       if (unlikely (item->format == (char) ('T'|0x80)))
12433*7304104dSAndroid Build Coastguard Worker 	{
12434*7304104dSAndroid Build Coastguard Worker 	  /* This is a hack for an ill-considered 64-bit ABI where
12435*7304104dSAndroid Build Coastguard Worker 	     tv_usec is actually a 32-bit field with 32 bits of padding
12436*7304104dSAndroid Build Coastguard Worker 	     rounding out struct timeval.  We've already converted it as
12437*7304104dSAndroid Build Coastguard Worker 	     a 64-bit field.  For little-endian, this just means the
12438*7304104dSAndroid Build Coastguard Worker 	     high half is the padding; it's presumably zero, but should
12439*7304104dSAndroid Build Coastguard Worker 	     be ignored anyway.  For big-endian, it means the 32-bit
12440*7304104dSAndroid Build Coastguard Worker 	     field went into the high half of USEC.  */
12441*7304104dSAndroid Build Coastguard Worker 	  GElf_Ehdr ehdr_mem;
12442*7304104dSAndroid Build Coastguard Worker 	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
12443*7304104dSAndroid Build Coastguard Worker 	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
12444*7304104dSAndroid Build Coastguard Worker 	    usec >>= 32;
12445*7304104dSAndroid Build Coastguard Worker 	  else
12446*7304104dSAndroid Build Coastguard Worker 	    usec &= UINT32_MAX;
12447*7304104dSAndroid Build Coastguard Worker 	}
12448*7304104dSAndroid Build Coastguard Worker       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
12449*7304104dSAndroid Build Coastguard Worker 			       "%" PRIu64 ".%.6" PRIu64, sec, usec);
12450*7304104dSAndroid Build Coastguard Worker       break;
12451*7304104dSAndroid Build Coastguard Worker 
12452*7304104dSAndroid Build Coastguard Worker     case 'c':
12453*7304104dSAndroid Build Coastguard Worker       assert (count == 1);
12454*7304104dSAndroid Build Coastguard Worker       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
12455*7304104dSAndroid Build Coastguard Worker 			       "%c", value_Byte[0]);
12456*7304104dSAndroid Build Coastguard Worker       break;
12457*7304104dSAndroid Build Coastguard Worker 
12458*7304104dSAndroid Build Coastguard Worker     case 's':
12459*7304104dSAndroid Build Coastguard Worker       colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
12460*7304104dSAndroid Build Coastguard Worker 			       "%.*s", (int) count, value_Byte);
12461*7304104dSAndroid Build Coastguard Worker       break;
12462*7304104dSAndroid Build Coastguard Worker 
12463*7304104dSAndroid Build Coastguard Worker     case '\n':
12464*7304104dSAndroid Build Coastguard Worker       /* This is a list of strings separated by '\n'.  */
12465*7304104dSAndroid Build Coastguard Worker       assert (item->count == 0);
12466*7304104dSAndroid Build Coastguard Worker       assert (repeated_size != NULL);
12467*7304104dSAndroid Build Coastguard Worker       assert (item->name == NULL);
12468*7304104dSAndroid Build Coastguard Worker       if (unlikely (item->offset >= *repeated_size))
12469*7304104dSAndroid Build Coastguard Worker 	break;
12470*7304104dSAndroid Build Coastguard Worker 
12471*7304104dSAndroid Build Coastguard Worker       const char *s = desc + item->offset;
12472*7304104dSAndroid Build Coastguard Worker       size = *repeated_size - item->offset;
12473*7304104dSAndroid Build Coastguard Worker       *repeated_size = 0;
12474*7304104dSAndroid Build Coastguard Worker       while (size > 0)
12475*7304104dSAndroid Build Coastguard Worker 	{
12476*7304104dSAndroid Build Coastguard Worker 	  const char *eol = memchr (s, '\n', size);
12477*7304104dSAndroid Build Coastguard Worker 	  int len = size;
12478*7304104dSAndroid Build Coastguard Worker 	  if (eol != NULL)
12479*7304104dSAndroid Build Coastguard Worker 	    len = eol - s;
12480*7304104dSAndroid Build Coastguard Worker 	  printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
12481*7304104dSAndroid Build Coastguard Worker 	  if (eol == NULL)
12482*7304104dSAndroid Build Coastguard Worker 	    break;
12483*7304104dSAndroid Build Coastguard Worker 	  size -= eol + 1 - s;
12484*7304104dSAndroid Build Coastguard Worker 	  s = eol + 1;
12485*7304104dSAndroid Build Coastguard Worker 	}
12486*7304104dSAndroid Build Coastguard Worker 
12487*7304104dSAndroid Build Coastguard Worker       colno = WRAP_COLUMN;
12488*7304104dSAndroid Build Coastguard Worker       break;
12489*7304104dSAndroid Build Coastguard Worker 
12490*7304104dSAndroid Build Coastguard Worker     case 'h':
12491*7304104dSAndroid Build Coastguard Worker       break;
12492*7304104dSAndroid Build Coastguard Worker 
12493*7304104dSAndroid Build Coastguard Worker     default:
12494*7304104dSAndroid Build Coastguard Worker       error (0, 0, "XXX not handling format '%c' for %s",
12495*7304104dSAndroid Build Coastguard Worker 	     item->format, item->name);
12496*7304104dSAndroid Build Coastguard Worker       break;
12497*7304104dSAndroid Build Coastguard Worker     }
12498*7304104dSAndroid Build Coastguard Worker 
12499*7304104dSAndroid Build Coastguard Worker #undef TYPES
12500*7304104dSAndroid Build Coastguard Worker 
12501*7304104dSAndroid Build Coastguard Worker   return colno;
12502*7304104dSAndroid Build Coastguard Worker }
12503*7304104dSAndroid Build Coastguard Worker 
12504*7304104dSAndroid Build Coastguard Worker 
12505*7304104dSAndroid Build Coastguard Worker /* Sort items by group, and by layout offset within each group.  */
12506*7304104dSAndroid Build Coastguard Worker static int
compare_core_items(const void * a,const void * b)12507*7304104dSAndroid Build Coastguard Worker compare_core_items (const void *a, const void *b)
12508*7304104dSAndroid Build Coastguard Worker {
12509*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *const *p1 = a;
12510*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *const *p2 = b;
12511*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *item1 = *p1;
12512*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *item2 = *p2;
12513*7304104dSAndroid Build Coastguard Worker 
12514*7304104dSAndroid Build Coastguard Worker   return ((item1->group == item2->group ? 0
12515*7304104dSAndroid Build Coastguard Worker 	   : strcmp (item1->group, item2->group))
12516*7304104dSAndroid Build Coastguard Worker 	  ?: (int) item1->offset - (int) item2->offset);
12517*7304104dSAndroid Build Coastguard Worker }
12518*7304104dSAndroid Build Coastguard Worker 
12519*7304104dSAndroid Build Coastguard Worker /* Sort item groups by layout offset of the first item in the group.  */
12520*7304104dSAndroid Build Coastguard Worker static int
compare_core_item_groups(const void * a,const void * b)12521*7304104dSAndroid Build Coastguard Worker compare_core_item_groups (const void *a, const void *b)
12522*7304104dSAndroid Build Coastguard Worker {
12523*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *const *const *p1 = a;
12524*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *const *const *p2 = b;
12525*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *const *group1 = *p1;
12526*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *const *group2 = *p2;
12527*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *item1 = *group1;
12528*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *item2 = *group2;
12529*7304104dSAndroid Build Coastguard Worker 
12530*7304104dSAndroid Build Coastguard Worker   return (int) item1->offset - (int) item2->offset;
12531*7304104dSAndroid Build Coastguard Worker }
12532*7304104dSAndroid Build Coastguard Worker 
12533*7304104dSAndroid Build Coastguard Worker static unsigned int
handle_core_items(Elf * core,const void * desc,size_t descsz,const Ebl_Core_Item * items,size_t nitems)12534*7304104dSAndroid Build Coastguard Worker handle_core_items (Elf *core, const void *desc, size_t descsz,
12535*7304104dSAndroid Build Coastguard Worker 		   const Ebl_Core_Item *items, size_t nitems)
12536*7304104dSAndroid Build Coastguard Worker {
12537*7304104dSAndroid Build Coastguard Worker   if (nitems == 0)
12538*7304104dSAndroid Build Coastguard Worker     return 0;
12539*7304104dSAndroid Build Coastguard Worker   unsigned int colno = 0;
12540*7304104dSAndroid Build Coastguard Worker 
12541*7304104dSAndroid Build Coastguard Worker   /* FORMAT '\n' makes sense to be present only as a single item as it
12542*7304104dSAndroid Build Coastguard Worker      processes all the data of a note.  FORMATs 'b' and 'B' have a special case
12543*7304104dSAndroid Build Coastguard Worker      if present as a single item but they can be also processed with other
12544*7304104dSAndroid Build Coastguard Worker      items below.  */
12545*7304104dSAndroid Build Coastguard Worker   if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
12546*7304104dSAndroid Build Coastguard Worker 		      || items[0].format == 'B'))
12547*7304104dSAndroid Build Coastguard Worker     {
12548*7304104dSAndroid Build Coastguard Worker       assert (items[0].offset == 0);
12549*7304104dSAndroid Build Coastguard Worker       size_t size = descsz;
12550*7304104dSAndroid Build Coastguard Worker       colno = handle_core_item (core, items, desc, colno, &size);
12551*7304104dSAndroid Build Coastguard Worker       /* If SIZE is not zero here there is some remaining data.  But we do not
12552*7304104dSAndroid Build Coastguard Worker 	 know how to process it anyway.  */
12553*7304104dSAndroid Build Coastguard Worker       return colno;
12554*7304104dSAndroid Build Coastguard Worker     }
12555*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nitems; ++i)
12556*7304104dSAndroid Build Coastguard Worker     assert (items[i].format != '\n');
12557*7304104dSAndroid Build Coastguard Worker 
12558*7304104dSAndroid Build Coastguard Worker   /* Sort to collect the groups together.  */
12559*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *sorted_items[nitems];
12560*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nitems; ++i)
12561*7304104dSAndroid Build Coastguard Worker     sorted_items[i] = &items[i];
12562*7304104dSAndroid Build Coastguard Worker   qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
12563*7304104dSAndroid Build Coastguard Worker 
12564*7304104dSAndroid Build Coastguard Worker   /* Collect the unique groups and sort them.  */
12565*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item **groups[nitems];
12566*7304104dSAndroid Build Coastguard Worker   groups[0] = &sorted_items[0];
12567*7304104dSAndroid Build Coastguard Worker   size_t ngroups = 1;
12568*7304104dSAndroid Build Coastguard Worker   for (size_t i = 1; i < nitems; ++i)
12569*7304104dSAndroid Build Coastguard Worker     if (sorted_items[i]->group != sorted_items[i - 1]->group
12570*7304104dSAndroid Build Coastguard Worker 	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
12571*7304104dSAndroid Build Coastguard Worker       groups[ngroups++] = &sorted_items[i];
12572*7304104dSAndroid Build Coastguard Worker   qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
12573*7304104dSAndroid Build Coastguard Worker 
12574*7304104dSAndroid Build Coastguard Worker   /* Write out all the groups.  */
12575*7304104dSAndroid Build Coastguard Worker   const void *last = desc;
12576*7304104dSAndroid Build Coastguard Worker   do
12577*7304104dSAndroid Build Coastguard Worker     {
12578*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < ngroups; ++i)
12579*7304104dSAndroid Build Coastguard Worker 	{
12580*7304104dSAndroid Build Coastguard Worker 	  for (const Ebl_Core_Item **item = groups[i];
12581*7304104dSAndroid Build Coastguard Worker 	       (item < &sorted_items[nitems]
12582*7304104dSAndroid Build Coastguard Worker 		&& ((*item)->group == groups[i][0]->group
12583*7304104dSAndroid Build Coastguard Worker 		    || !strcmp ((*item)->group, groups[i][0]->group)));
12584*7304104dSAndroid Build Coastguard Worker 	       ++item)
12585*7304104dSAndroid Build Coastguard Worker 	    colno = handle_core_item (core, *item, desc, colno, NULL);
12586*7304104dSAndroid Build Coastguard Worker 
12587*7304104dSAndroid Build Coastguard Worker 	  /* Force a line break at the end of the group.  */
12588*7304104dSAndroid Build Coastguard Worker 	  colno = WRAP_COLUMN;
12589*7304104dSAndroid Build Coastguard Worker 	}
12590*7304104dSAndroid Build Coastguard Worker 
12591*7304104dSAndroid Build Coastguard Worker       if (descsz == 0)
12592*7304104dSAndroid Build Coastguard Worker 	break;
12593*7304104dSAndroid Build Coastguard Worker 
12594*7304104dSAndroid Build Coastguard Worker       /* This set of items consumed a certain amount of the note's data.
12595*7304104dSAndroid Build Coastguard Worker 	 If there is more data there, we have another unit of the same size.
12596*7304104dSAndroid Build Coastguard Worker 	 Loop to print that out too.  */
12597*7304104dSAndroid Build Coastguard Worker       const Ebl_Core_Item *item = &items[nitems - 1];
12598*7304104dSAndroid Build Coastguard Worker       size_t eltsz = item->offset + gelf_fsize (core, item->type,
12599*7304104dSAndroid Build Coastguard Worker 						item->count ?: 1, EV_CURRENT);
12600*7304104dSAndroid Build Coastguard Worker 
12601*7304104dSAndroid Build Coastguard Worker       int reps = -1;
12602*7304104dSAndroid Build Coastguard Worker       do
12603*7304104dSAndroid Build Coastguard Worker 	{
12604*7304104dSAndroid Build Coastguard Worker 	  ++reps;
12605*7304104dSAndroid Build Coastguard Worker 	  desc += eltsz;
12606*7304104dSAndroid Build Coastguard Worker 	  descsz -= eltsz;
12607*7304104dSAndroid Build Coastguard Worker 	}
12608*7304104dSAndroid Build Coastguard Worker       while (descsz >= eltsz && !memcmp (desc, last, eltsz));
12609*7304104dSAndroid Build Coastguard Worker 
12610*7304104dSAndroid Build Coastguard Worker       if (reps == 1)
12611*7304104dSAndroid Build Coastguard Worker 	{
12612*7304104dSAndroid Build Coastguard Worker 	  /* For just one repeat, print it unabridged twice.  */
12613*7304104dSAndroid Build Coastguard Worker 	  desc -= eltsz;
12614*7304104dSAndroid Build Coastguard Worker 	  descsz += eltsz;
12615*7304104dSAndroid Build Coastguard Worker 	}
12616*7304104dSAndroid Build Coastguard Worker       else if (reps > 1)
12617*7304104dSAndroid Build Coastguard Worker 	printf (_("\n%*s... <repeats %u more times> ..."),
12618*7304104dSAndroid Build Coastguard Worker 		ITEM_INDENT, "", reps);
12619*7304104dSAndroid Build Coastguard Worker 
12620*7304104dSAndroid Build Coastguard Worker       last = desc;
12621*7304104dSAndroid Build Coastguard Worker     }
12622*7304104dSAndroid Build Coastguard Worker   while (descsz > 0);
12623*7304104dSAndroid Build Coastguard Worker 
12624*7304104dSAndroid Build Coastguard Worker   return colno;
12625*7304104dSAndroid Build Coastguard Worker }
12626*7304104dSAndroid Build Coastguard Worker 
12627*7304104dSAndroid Build Coastguard Worker static unsigned int
handle_core_register(Ebl * ebl,Elf * core,int maxregname,const Ebl_Register_Location * regloc,const void * desc,unsigned int colno)12628*7304104dSAndroid Build Coastguard Worker handle_core_register (Ebl *ebl, Elf *core, int maxregname,
12629*7304104dSAndroid Build Coastguard Worker 		      const Ebl_Register_Location *regloc, const void *desc,
12630*7304104dSAndroid Build Coastguard Worker 		      unsigned int colno)
12631*7304104dSAndroid Build Coastguard Worker {
12632*7304104dSAndroid Build Coastguard Worker   if (regloc->bits % 8 != 0)
12633*7304104dSAndroid Build Coastguard Worker     {
12634*7304104dSAndroid Build Coastguard Worker       error (0, 0, "Warning: Cannot handle register with %" PRIu8 "bits\n",
12635*7304104dSAndroid Build Coastguard Worker 	     regloc->bits);
12636*7304104dSAndroid Build Coastguard Worker       return colno;
12637*7304104dSAndroid Build Coastguard Worker     }
12638*7304104dSAndroid Build Coastguard Worker 
12639*7304104dSAndroid Build Coastguard Worker   desc += regloc->offset;
12640*7304104dSAndroid Build Coastguard Worker 
12641*7304104dSAndroid Build Coastguard Worker   for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
12642*7304104dSAndroid Build Coastguard Worker     {
12643*7304104dSAndroid Build Coastguard Worker       char name[REGNAMESZ];
12644*7304104dSAndroid Build Coastguard Worker       int bits;
12645*7304104dSAndroid Build Coastguard Worker       int type;
12646*7304104dSAndroid Build Coastguard Worker       register_info (ebl, reg, regloc, name, &bits, &type);
12647*7304104dSAndroid Build Coastguard Worker 
12648*7304104dSAndroid Build Coastguard Worker #define TYPES								      \
12649*7304104dSAndroid Build Coastguard Worker       BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8);			      \
12650*7304104dSAndroid Build Coastguard Worker       BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16);			      \
12651*7304104dSAndroid Build Coastguard Worker       BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32);			      \
12652*7304104dSAndroid Build Coastguard Worker       BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64)
12653*7304104dSAndroid Build Coastguard Worker 
12654*7304104dSAndroid Build Coastguard Worker #define BITS(bits, xtype, sfmt, ufmt)				\
12655*7304104dSAndroid Build Coastguard Worker       uint##bits##_t b##bits; int##bits##_t b##bits##s
12656*7304104dSAndroid Build Coastguard Worker       union { TYPES; uint64_t b128[2]; } value;
12657*7304104dSAndroid Build Coastguard Worker #undef	BITS
12658*7304104dSAndroid Build Coastguard Worker 
12659*7304104dSAndroid Build Coastguard Worker       switch (type)
12660*7304104dSAndroid Build Coastguard Worker 	{
12661*7304104dSAndroid Build Coastguard Worker 	case DW_ATE_unsigned:
12662*7304104dSAndroid Build Coastguard Worker 	case DW_ATE_signed:
12663*7304104dSAndroid Build Coastguard Worker 	case DW_ATE_address:
12664*7304104dSAndroid Build Coastguard Worker 	  switch (bits)
12665*7304104dSAndroid Build Coastguard Worker 	    {
12666*7304104dSAndroid Build Coastguard Worker #define BITS(bits, xtype, sfmt, ufmt)					      \
12667*7304104dSAndroid Build Coastguard Worker 	    case bits:							      \
12668*7304104dSAndroid Build Coastguard Worker 	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
12669*7304104dSAndroid Build Coastguard Worker 	      if (type == DW_ATE_signed)				      \
12670*7304104dSAndroid Build Coastguard Worker 		colno = print_core_item (colno, ' ', WRAP_COLUMN,	      \
12671*7304104dSAndroid Build Coastguard Worker 					 maxregname, name,		      \
12672*7304104dSAndroid Build Coastguard Worker 					 sfmt, value.b##bits##s);	      \
12673*7304104dSAndroid Build Coastguard Worker 	      else							      \
12674*7304104dSAndroid Build Coastguard Worker 		colno = print_core_item (colno, ' ', WRAP_COLUMN,	      \
12675*7304104dSAndroid Build Coastguard Worker 					 maxregname, name,		      \
12676*7304104dSAndroid Build Coastguard Worker 					 ufmt, value.b##bits);		      \
12677*7304104dSAndroid Build Coastguard Worker 	      break
12678*7304104dSAndroid Build Coastguard Worker 
12679*7304104dSAndroid Build Coastguard Worker 	    TYPES;
12680*7304104dSAndroid Build Coastguard Worker 
12681*7304104dSAndroid Build Coastguard Worker 	    case 128:
12682*7304104dSAndroid Build Coastguard Worker 	      assert (type == DW_ATE_unsigned);
12683*7304104dSAndroid Build Coastguard Worker 	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
12684*7304104dSAndroid Build Coastguard Worker 	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
12685*7304104dSAndroid Build Coastguard Worker 	      colno = print_core_item (colno, ' ', WRAP_COLUMN,
12686*7304104dSAndroid Build Coastguard Worker 				       maxregname, name,
12687*7304104dSAndroid Build Coastguard Worker 				       "0x%.16" PRIx64 "%.16" PRIx64,
12688*7304104dSAndroid Build Coastguard Worker 				       value.b128[!be], value.b128[be]);
12689*7304104dSAndroid Build Coastguard Worker 	      break;
12690*7304104dSAndroid Build Coastguard Worker 
12691*7304104dSAndroid Build Coastguard Worker 	    default:
12692*7304104dSAndroid Build Coastguard Worker 	      abort ();
12693*7304104dSAndroid Build Coastguard Worker #undef	BITS
12694*7304104dSAndroid Build Coastguard Worker 	    }
12695*7304104dSAndroid Build Coastguard Worker 	  break;
12696*7304104dSAndroid Build Coastguard Worker 
12697*7304104dSAndroid Build Coastguard Worker 	default:
12698*7304104dSAndroid Build Coastguard Worker 	  /* Print each byte in hex, the whole thing in native byte order.  */
12699*7304104dSAndroid Build Coastguard Worker 	  assert (bits % 8 == 0);
12700*7304104dSAndroid Build Coastguard Worker 	  const uint8_t *bytes = desc;
12701*7304104dSAndroid Build Coastguard Worker 	  desc += bits / 8;
12702*7304104dSAndroid Build Coastguard Worker 	  char hex[bits / 4 + 1];
12703*7304104dSAndroid Build Coastguard Worker 	  hex[bits / 4] = '\0';
12704*7304104dSAndroid Build Coastguard Worker 	  int incr = 1;
12705*7304104dSAndroid Build Coastguard Worker 	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
12706*7304104dSAndroid Build Coastguard Worker 	    {
12707*7304104dSAndroid Build Coastguard Worker 	      bytes += bits / 8 - 1;
12708*7304104dSAndroid Build Coastguard Worker 	      incr = -1;
12709*7304104dSAndroid Build Coastguard Worker 	    }
12710*7304104dSAndroid Build Coastguard Worker 	  size_t idx = 0;
12711*7304104dSAndroid Build Coastguard Worker 	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
12712*7304104dSAndroid Build Coastguard Worker 	    {
12713*7304104dSAndroid Build Coastguard Worker 	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
12714*7304104dSAndroid Build Coastguard Worker 	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
12715*7304104dSAndroid Build Coastguard Worker 	    }
12716*7304104dSAndroid Build Coastguard Worker 	  colno = print_core_item (colno, ' ', WRAP_COLUMN,
12717*7304104dSAndroid Build Coastguard Worker 				   maxregname, name, "0x%s", hex);
12718*7304104dSAndroid Build Coastguard Worker 	  break;
12719*7304104dSAndroid Build Coastguard Worker 	}
12720*7304104dSAndroid Build Coastguard Worker       desc += regloc->pad;
12721*7304104dSAndroid Build Coastguard Worker 
12722*7304104dSAndroid Build Coastguard Worker #undef TYPES
12723*7304104dSAndroid Build Coastguard Worker     }
12724*7304104dSAndroid Build Coastguard Worker 
12725*7304104dSAndroid Build Coastguard Worker   return colno;
12726*7304104dSAndroid Build Coastguard Worker }
12727*7304104dSAndroid Build Coastguard Worker 
12728*7304104dSAndroid Build Coastguard Worker 
12729*7304104dSAndroid Build Coastguard Worker struct register_info
12730*7304104dSAndroid Build Coastguard Worker {
12731*7304104dSAndroid Build Coastguard Worker   const Ebl_Register_Location *regloc;
12732*7304104dSAndroid Build Coastguard Worker   const char *set;
12733*7304104dSAndroid Build Coastguard Worker   char name[REGNAMESZ];
12734*7304104dSAndroid Build Coastguard Worker   int regno;
12735*7304104dSAndroid Build Coastguard Worker   int bits;
12736*7304104dSAndroid Build Coastguard Worker   int type;
12737*7304104dSAndroid Build Coastguard Worker };
12738*7304104dSAndroid Build Coastguard Worker 
12739*7304104dSAndroid Build Coastguard Worker static int
register_bitpos(const struct register_info * r)12740*7304104dSAndroid Build Coastguard Worker register_bitpos (const struct register_info *r)
12741*7304104dSAndroid Build Coastguard Worker {
12742*7304104dSAndroid Build Coastguard Worker   return (r->regloc->offset * 8
12743*7304104dSAndroid Build Coastguard Worker 	  + ((r->regno - r->regloc->regno)
12744*7304104dSAndroid Build Coastguard Worker 	     * (r->regloc->bits + r->regloc->pad * 8)));
12745*7304104dSAndroid Build Coastguard Worker }
12746*7304104dSAndroid Build Coastguard Worker 
12747*7304104dSAndroid Build Coastguard Worker static int
compare_sets_by_info(const struct register_info * r1,const struct register_info * r2)12748*7304104dSAndroid Build Coastguard Worker compare_sets_by_info (const struct register_info *r1,
12749*7304104dSAndroid Build Coastguard Worker 		      const struct register_info *r2)
12750*7304104dSAndroid Build Coastguard Worker {
12751*7304104dSAndroid Build Coastguard Worker   return ((int) r2->bits - (int) r1->bits
12752*7304104dSAndroid Build Coastguard Worker 	  ?: register_bitpos (r1) - register_bitpos (r2));
12753*7304104dSAndroid Build Coastguard Worker }
12754*7304104dSAndroid Build Coastguard Worker 
12755*7304104dSAndroid Build Coastguard Worker /* Sort registers by set, and by size and layout offset within each set.  */
12756*7304104dSAndroid Build Coastguard Worker static int
compare_registers(const void * a,const void * b)12757*7304104dSAndroid Build Coastguard Worker compare_registers (const void *a, const void *b)
12758*7304104dSAndroid Build Coastguard Worker {
12759*7304104dSAndroid Build Coastguard Worker   const struct register_info *r1 = a;
12760*7304104dSAndroid Build Coastguard Worker   const struct register_info *r2 = b;
12761*7304104dSAndroid Build Coastguard Worker 
12762*7304104dSAndroid Build Coastguard Worker   /* Unused elements sort last.  */
12763*7304104dSAndroid Build Coastguard Worker   if (r1->regloc == NULL)
12764*7304104dSAndroid Build Coastguard Worker     return r2->regloc == NULL ? 0 : 1;
12765*7304104dSAndroid Build Coastguard Worker   if (r2->regloc == NULL)
12766*7304104dSAndroid Build Coastguard Worker     return -1;
12767*7304104dSAndroid Build Coastguard Worker 
12768*7304104dSAndroid Build Coastguard Worker   return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
12769*7304104dSAndroid Build Coastguard Worker 	  ?: compare_sets_by_info (r1, r2));
12770*7304104dSAndroid Build Coastguard Worker }
12771*7304104dSAndroid Build Coastguard Worker 
12772*7304104dSAndroid Build Coastguard Worker /* Sort register sets by layout offset of the first register in the set.  */
12773*7304104dSAndroid Build Coastguard Worker static int
compare_register_sets(const void * a,const void * b)12774*7304104dSAndroid Build Coastguard Worker compare_register_sets (const void *a, const void *b)
12775*7304104dSAndroid Build Coastguard Worker {
12776*7304104dSAndroid Build Coastguard Worker   const struct register_info *const *p1 = a;
12777*7304104dSAndroid Build Coastguard Worker   const struct register_info *const *p2 = b;
12778*7304104dSAndroid Build Coastguard Worker   return compare_sets_by_info (*p1, *p2);
12779*7304104dSAndroid Build Coastguard Worker }
12780*7304104dSAndroid Build Coastguard Worker 
12781*7304104dSAndroid Build Coastguard Worker static inline bool
same_set(const struct register_info * a,const struct register_info * b,const struct register_info * regs,size_t maxnreg)12782*7304104dSAndroid Build Coastguard Worker same_set (const struct register_info *a,
12783*7304104dSAndroid Build Coastguard Worker 	  const struct register_info *b,
12784*7304104dSAndroid Build Coastguard Worker 	  const struct register_info *regs,
12785*7304104dSAndroid Build Coastguard Worker 	  size_t maxnreg)
12786*7304104dSAndroid Build Coastguard Worker {
12787*7304104dSAndroid Build Coastguard Worker   return (a < &regs[maxnreg] && a->regloc != NULL
12788*7304104dSAndroid Build Coastguard Worker 	  && b < &regs[maxnreg] && b->regloc != NULL
12789*7304104dSAndroid Build Coastguard Worker 	  && a->bits == b->bits
12790*7304104dSAndroid Build Coastguard Worker 	  && (a->set == b->set || !strcmp (a->set, b->set)));
12791*7304104dSAndroid Build Coastguard Worker }
12792*7304104dSAndroid Build Coastguard Worker 
12793*7304104dSAndroid Build Coastguard Worker static unsigned int
handle_core_registers(Ebl * ebl,Elf * core,const void * desc,const Ebl_Register_Location * reglocs,size_t nregloc)12794*7304104dSAndroid Build Coastguard Worker handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
12795*7304104dSAndroid Build Coastguard Worker 		       const Ebl_Register_Location *reglocs, size_t nregloc)
12796*7304104dSAndroid Build Coastguard Worker {
12797*7304104dSAndroid Build Coastguard Worker   if (nregloc == 0)
12798*7304104dSAndroid Build Coastguard Worker     return 0;
12799*7304104dSAndroid Build Coastguard Worker 
12800*7304104dSAndroid Build Coastguard Worker   ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
12801*7304104dSAndroid Build Coastguard Worker   if (maxnreg <= 0)
12802*7304104dSAndroid Build Coastguard Worker     {
12803*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < nregloc; ++i)
12804*7304104dSAndroid Build Coastguard Worker 	if (maxnreg < reglocs[i].regno + reglocs[i].count)
12805*7304104dSAndroid Build Coastguard Worker 	  maxnreg = reglocs[i].regno + reglocs[i].count;
12806*7304104dSAndroid Build Coastguard Worker       assert (maxnreg > 0);
12807*7304104dSAndroid Build Coastguard Worker     }
12808*7304104dSAndroid Build Coastguard Worker 
12809*7304104dSAndroid Build Coastguard Worker   struct register_info regs[maxnreg];
12810*7304104dSAndroid Build Coastguard Worker   memset (regs, 0, sizeof regs);
12811*7304104dSAndroid Build Coastguard Worker 
12812*7304104dSAndroid Build Coastguard Worker   /* Sort to collect the sets together.  */
12813*7304104dSAndroid Build Coastguard Worker   int maxreg = 0;
12814*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nregloc; ++i)
12815*7304104dSAndroid Build Coastguard Worker     for (int reg = reglocs[i].regno;
12816*7304104dSAndroid Build Coastguard Worker 	 reg < reglocs[i].regno + reglocs[i].count;
12817*7304104dSAndroid Build Coastguard Worker 	 ++reg)
12818*7304104dSAndroid Build Coastguard Worker       {
12819*7304104dSAndroid Build Coastguard Worker 	assert (reg < maxnreg);
12820*7304104dSAndroid Build Coastguard Worker 	if (reg > maxreg)
12821*7304104dSAndroid Build Coastguard Worker 	  maxreg = reg;
12822*7304104dSAndroid Build Coastguard Worker 	struct register_info *info = &regs[reg];
12823*7304104dSAndroid Build Coastguard Worker 	info->regloc = &reglocs[i];
12824*7304104dSAndroid Build Coastguard Worker 	info->regno = reg;
12825*7304104dSAndroid Build Coastguard Worker 	info->set = register_info (ebl, reg, &reglocs[i],
12826*7304104dSAndroid Build Coastguard Worker 				   info->name, &info->bits, &info->type);
12827*7304104dSAndroid Build Coastguard Worker       }
12828*7304104dSAndroid Build Coastguard Worker   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
12829*7304104dSAndroid Build Coastguard Worker 
12830*7304104dSAndroid Build Coastguard Worker   /* Collect the unique sets and sort them.  */
12831*7304104dSAndroid Build Coastguard Worker   struct register_info *sets[maxreg + 1];
12832*7304104dSAndroid Build Coastguard Worker   sets[0] = &regs[0];
12833*7304104dSAndroid Build Coastguard Worker   size_t nsets = 1;
12834*7304104dSAndroid Build Coastguard Worker   for (int i = 1; i <= maxreg; ++i)
12835*7304104dSAndroid Build Coastguard Worker     if (regs[i].regloc != NULL
12836*7304104dSAndroid Build Coastguard Worker 	&& !same_set (&regs[i], &regs[i - 1], regs, maxnreg))
12837*7304104dSAndroid Build Coastguard Worker       sets[nsets++] = &regs[i];
12838*7304104dSAndroid Build Coastguard Worker   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
12839*7304104dSAndroid Build Coastguard Worker 
12840*7304104dSAndroid Build Coastguard Worker   /* Write out all the sets.  */
12841*7304104dSAndroid Build Coastguard Worker   unsigned int colno = 0;
12842*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nsets; ++i)
12843*7304104dSAndroid Build Coastguard Worker     {
12844*7304104dSAndroid Build Coastguard Worker       /* Find the longest name of a register in this set.  */
12845*7304104dSAndroid Build Coastguard Worker       size_t maxname = 0;
12846*7304104dSAndroid Build Coastguard Worker       const struct register_info *end;
12847*7304104dSAndroid Build Coastguard Worker       for (end = sets[i]; same_set (sets[i], end, regs, maxnreg); ++end)
12848*7304104dSAndroid Build Coastguard Worker 	{
12849*7304104dSAndroid Build Coastguard Worker 	  size_t len = strlen (end->name);
12850*7304104dSAndroid Build Coastguard Worker 	  if (len > maxname)
12851*7304104dSAndroid Build Coastguard Worker 	    maxname = len;
12852*7304104dSAndroid Build Coastguard Worker 	}
12853*7304104dSAndroid Build Coastguard Worker 
12854*7304104dSAndroid Build Coastguard Worker       for (const struct register_info *reg = sets[i];
12855*7304104dSAndroid Build Coastguard Worker 	   reg < end;
12856*7304104dSAndroid Build Coastguard Worker 	   reg += reg->regloc->count ?: 1)
12857*7304104dSAndroid Build Coastguard Worker 	colno = handle_core_register (ebl, core, maxname,
12858*7304104dSAndroid Build Coastguard Worker 				      reg->regloc, desc, colno);
12859*7304104dSAndroid Build Coastguard Worker 
12860*7304104dSAndroid Build Coastguard Worker       /* Force a line break at the end of the group.  */
12861*7304104dSAndroid Build Coastguard Worker       colno = WRAP_COLUMN;
12862*7304104dSAndroid Build Coastguard Worker     }
12863*7304104dSAndroid Build Coastguard Worker 
12864*7304104dSAndroid Build Coastguard Worker   return colno;
12865*7304104dSAndroid Build Coastguard Worker }
12866*7304104dSAndroid Build Coastguard Worker 
12867*7304104dSAndroid Build Coastguard Worker static void
handle_auxv_note(Ebl * ebl,Elf * core,GElf_Word descsz,GElf_Off desc_pos)12868*7304104dSAndroid Build Coastguard Worker handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
12869*7304104dSAndroid Build Coastguard Worker {
12870*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
12871*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
12872*7304104dSAndroid Build Coastguard Worker   elf_error:
12873*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot convert core note data: %s"), elf_errmsg (-1));
12874*7304104dSAndroid Build Coastguard Worker 
12875*7304104dSAndroid Build Coastguard Worker   const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
12876*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < nauxv; ++i)
12877*7304104dSAndroid Build Coastguard Worker     {
12878*7304104dSAndroid Build Coastguard Worker       GElf_auxv_t av_mem;
12879*7304104dSAndroid Build Coastguard Worker       GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
12880*7304104dSAndroid Build Coastguard Worker       if (av == NULL)
12881*7304104dSAndroid Build Coastguard Worker 	goto elf_error;
12882*7304104dSAndroid Build Coastguard Worker 
12883*7304104dSAndroid Build Coastguard Worker       const char *name;
12884*7304104dSAndroid Build Coastguard Worker       const char *fmt;
12885*7304104dSAndroid Build Coastguard Worker       if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
12886*7304104dSAndroid Build Coastguard Worker 	{
12887*7304104dSAndroid Build Coastguard Worker 	  /* Unknown type.  */
12888*7304104dSAndroid Build Coastguard Worker 	  if (av->a_un.a_val == 0)
12889*7304104dSAndroid Build Coastguard Worker 	    printf ("    %" PRIu64 "\n", av->a_type);
12890*7304104dSAndroid Build Coastguard Worker 	  else
12891*7304104dSAndroid Build Coastguard Worker 	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
12892*7304104dSAndroid Build Coastguard Worker 		    av->a_type, av->a_un.a_val);
12893*7304104dSAndroid Build Coastguard Worker 	}
12894*7304104dSAndroid Build Coastguard Worker       else
12895*7304104dSAndroid Build Coastguard Worker 	switch (fmt[0])
12896*7304104dSAndroid Build Coastguard Worker 	  {
12897*7304104dSAndroid Build Coastguard Worker 	  case '\0':		/* Normally zero.  */
12898*7304104dSAndroid Build Coastguard Worker 	    if (av->a_un.a_val == 0)
12899*7304104dSAndroid Build Coastguard Worker 	      {
12900*7304104dSAndroid Build Coastguard Worker 		printf ("    %s\n", name);
12901*7304104dSAndroid Build Coastguard Worker 		break;
12902*7304104dSAndroid Build Coastguard Worker 	      }
12903*7304104dSAndroid Build Coastguard Worker 	    FALLTHROUGH;
12904*7304104dSAndroid Build Coastguard Worker 	  case 'x':		/* hex */
12905*7304104dSAndroid Build Coastguard Worker 	  case 'p':		/* address */
12906*7304104dSAndroid Build Coastguard Worker 	  case 's':		/* address of string */
12907*7304104dSAndroid Build Coastguard Worker 	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
12908*7304104dSAndroid Build Coastguard Worker 	    break;
12909*7304104dSAndroid Build Coastguard Worker 	  case 'u':
12910*7304104dSAndroid Build Coastguard Worker 	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
12911*7304104dSAndroid Build Coastguard Worker 	    break;
12912*7304104dSAndroid Build Coastguard Worker 	  case 'd':
12913*7304104dSAndroid Build Coastguard Worker 	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
12914*7304104dSAndroid Build Coastguard Worker 	    break;
12915*7304104dSAndroid Build Coastguard Worker 
12916*7304104dSAndroid Build Coastguard Worker 	  case 'b':
12917*7304104dSAndroid Build Coastguard Worker 	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
12918*7304104dSAndroid Build Coastguard Worker 	    GElf_Xword bit = 1;
12919*7304104dSAndroid Build Coastguard Worker 	    const char *pfx = "<";
12920*7304104dSAndroid Build Coastguard Worker 	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
12921*7304104dSAndroid Build Coastguard Worker 	      {
12922*7304104dSAndroid Build Coastguard Worker 		if (av->a_un.a_val & bit)
12923*7304104dSAndroid Build Coastguard Worker 		  {
12924*7304104dSAndroid Build Coastguard Worker 		    printf ("%s%s", pfx, p);
12925*7304104dSAndroid Build Coastguard Worker 		    pfx = " ";
12926*7304104dSAndroid Build Coastguard Worker 		  }
12927*7304104dSAndroid Build Coastguard Worker 		bit <<= 1;
12928*7304104dSAndroid Build Coastguard Worker 	      }
12929*7304104dSAndroid Build Coastguard Worker 	    printf (">\n");
12930*7304104dSAndroid Build Coastguard Worker 	    break;
12931*7304104dSAndroid Build Coastguard Worker 
12932*7304104dSAndroid Build Coastguard Worker 	  default:
12933*7304104dSAndroid Build Coastguard Worker 	    abort ();
12934*7304104dSAndroid Build Coastguard Worker 	  }
12935*7304104dSAndroid Build Coastguard Worker     }
12936*7304104dSAndroid Build Coastguard Worker }
12937*7304104dSAndroid Build Coastguard Worker 
12938*7304104dSAndroid Build Coastguard Worker static bool
buf_has_data(unsigned char const * ptr,unsigned char const * end,size_t sz)12939*7304104dSAndroid Build Coastguard Worker buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
12940*7304104dSAndroid Build Coastguard Worker {
12941*7304104dSAndroid Build Coastguard Worker   return ptr < end && (size_t) (end - ptr) >= sz;
12942*7304104dSAndroid Build Coastguard Worker }
12943*7304104dSAndroid Build Coastguard Worker 
12944*7304104dSAndroid Build Coastguard Worker static bool
buf_read_int(Elf * core,unsigned char const ** ptrp,unsigned char const * end,int * retp)12945*7304104dSAndroid Build Coastguard Worker buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
12946*7304104dSAndroid Build Coastguard Worker 	      int *retp)
12947*7304104dSAndroid Build Coastguard Worker {
12948*7304104dSAndroid Build Coastguard Worker   if (! buf_has_data (*ptrp, end, 4))
12949*7304104dSAndroid Build Coastguard Worker     return false;
12950*7304104dSAndroid Build Coastguard Worker 
12951*7304104dSAndroid Build Coastguard Worker   *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
12952*7304104dSAndroid Build Coastguard Worker   return true;
12953*7304104dSAndroid Build Coastguard Worker }
12954*7304104dSAndroid Build Coastguard Worker 
12955*7304104dSAndroid Build Coastguard Worker static bool
buf_read_ulong(Elf * core,unsigned char const ** ptrp,unsigned char const * end,uint64_t * retp)12956*7304104dSAndroid Build Coastguard Worker buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
12957*7304104dSAndroid Build Coastguard Worker 		uint64_t *retp)
12958*7304104dSAndroid Build Coastguard Worker {
12959*7304104dSAndroid Build Coastguard Worker   size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
12960*7304104dSAndroid Build Coastguard Worker   if (! buf_has_data (*ptrp, end, sz))
12961*7304104dSAndroid Build Coastguard Worker     return false;
12962*7304104dSAndroid Build Coastguard Worker 
12963*7304104dSAndroid Build Coastguard Worker   union
12964*7304104dSAndroid Build Coastguard Worker   {
12965*7304104dSAndroid Build Coastguard Worker     uint64_t u64;
12966*7304104dSAndroid Build Coastguard Worker     uint32_t u32;
12967*7304104dSAndroid Build Coastguard Worker   } u;
12968*7304104dSAndroid Build Coastguard Worker 
12969*7304104dSAndroid Build Coastguard Worker   *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
12970*7304104dSAndroid Build Coastguard Worker 
12971*7304104dSAndroid Build Coastguard Worker   if (sz == 4)
12972*7304104dSAndroid Build Coastguard Worker     *retp = u.u32;
12973*7304104dSAndroid Build Coastguard Worker   else
12974*7304104dSAndroid Build Coastguard Worker     *retp = u.u64;
12975*7304104dSAndroid Build Coastguard Worker   return true;
12976*7304104dSAndroid Build Coastguard Worker }
12977*7304104dSAndroid Build Coastguard Worker 
12978*7304104dSAndroid Build Coastguard Worker static void
handle_siginfo_note(Elf * core,GElf_Word descsz,GElf_Off desc_pos)12979*7304104dSAndroid Build Coastguard Worker handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
12980*7304104dSAndroid Build Coastguard Worker {
12981*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
12982*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
12983*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot convert core note data: %s"), elf_errmsg (-1));
12984*7304104dSAndroid Build Coastguard Worker 
12985*7304104dSAndroid Build Coastguard Worker   unsigned char const *ptr = data->d_buf;
12986*7304104dSAndroid Build Coastguard Worker   unsigned char const *const end = data->d_buf + data->d_size;
12987*7304104dSAndroid Build Coastguard Worker 
12988*7304104dSAndroid Build Coastguard Worker   /* Siginfo head is three ints: signal number, error number, origin
12989*7304104dSAndroid Build Coastguard Worker      code.  */
12990*7304104dSAndroid Build Coastguard Worker   int si_signo, si_errno, si_code;
12991*7304104dSAndroid Build Coastguard Worker   if (! buf_read_int (core, &ptr, end, &si_signo)
12992*7304104dSAndroid Build Coastguard Worker       || ! buf_read_int (core, &ptr, end, &si_errno)
12993*7304104dSAndroid Build Coastguard Worker       || ! buf_read_int (core, &ptr, end, &si_code))
12994*7304104dSAndroid Build Coastguard Worker     {
12995*7304104dSAndroid Build Coastguard Worker     fail:
12996*7304104dSAndroid Build Coastguard Worker       printf ("    Not enough data in NT_SIGINFO note.\n");
12997*7304104dSAndroid Build Coastguard Worker       return;
12998*7304104dSAndroid Build Coastguard Worker     }
12999*7304104dSAndroid Build Coastguard Worker 
13000*7304104dSAndroid Build Coastguard Worker   /* Next is a pointer-aligned union of structures.  On 64-bit
13001*7304104dSAndroid Build Coastguard Worker      machines, that implies a word of padding.  */
13002*7304104dSAndroid Build Coastguard Worker   if (gelf_getclass (core) == ELFCLASS64)
13003*7304104dSAndroid Build Coastguard Worker     ptr += 4;
13004*7304104dSAndroid Build Coastguard Worker 
13005*7304104dSAndroid Build Coastguard Worker   printf ("    si_signo: %d, si_errno: %d, si_code: %d\n",
13006*7304104dSAndroid Build Coastguard Worker 	  si_signo, si_errno, si_code);
13007*7304104dSAndroid Build Coastguard Worker 
13008*7304104dSAndroid Build Coastguard Worker   if (si_code > 0)
13009*7304104dSAndroid Build Coastguard Worker     switch (si_signo)
13010*7304104dSAndroid Build Coastguard Worker       {
13011*7304104dSAndroid Build Coastguard Worker       case CORE_SIGILL:
13012*7304104dSAndroid Build Coastguard Worker       case CORE_SIGFPE:
13013*7304104dSAndroid Build Coastguard Worker       case CORE_SIGSEGV:
13014*7304104dSAndroid Build Coastguard Worker       case CORE_SIGBUS:
13015*7304104dSAndroid Build Coastguard Worker 	{
13016*7304104dSAndroid Build Coastguard Worker 	  uint64_t addr;
13017*7304104dSAndroid Build Coastguard Worker 	  if (! buf_read_ulong (core, &ptr, end, &addr))
13018*7304104dSAndroid Build Coastguard Worker 	    goto fail;
13019*7304104dSAndroid Build Coastguard Worker 	  printf ("    fault address: %#" PRIx64 "\n", addr);
13020*7304104dSAndroid Build Coastguard Worker 	  break;
13021*7304104dSAndroid Build Coastguard Worker 	}
13022*7304104dSAndroid Build Coastguard Worker       default:
13023*7304104dSAndroid Build Coastguard Worker 	;
13024*7304104dSAndroid Build Coastguard Worker       }
13025*7304104dSAndroid Build Coastguard Worker   else if (si_code == CORE_SI_USER)
13026*7304104dSAndroid Build Coastguard Worker     {
13027*7304104dSAndroid Build Coastguard Worker       int pid, uid;
13028*7304104dSAndroid Build Coastguard Worker       if (! buf_read_int (core, &ptr, end, &pid)
13029*7304104dSAndroid Build Coastguard Worker 	  || ! buf_read_int (core, &ptr, end, &uid))
13030*7304104dSAndroid Build Coastguard Worker 	goto fail;
13031*7304104dSAndroid Build Coastguard Worker       printf ("    sender PID: %d, sender UID: %d\n", pid, uid);
13032*7304104dSAndroid Build Coastguard Worker     }
13033*7304104dSAndroid Build Coastguard Worker }
13034*7304104dSAndroid Build Coastguard Worker 
13035*7304104dSAndroid Build Coastguard Worker static void
handle_file_note(Elf * core,GElf_Word descsz,GElf_Off desc_pos)13036*7304104dSAndroid Build Coastguard Worker handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
13037*7304104dSAndroid Build Coastguard Worker {
13038*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
13039*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
13040*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot convert core note data: %s"), elf_errmsg (-1));
13041*7304104dSAndroid Build Coastguard Worker 
13042*7304104dSAndroid Build Coastguard Worker   unsigned char const *ptr = data->d_buf;
13043*7304104dSAndroid Build Coastguard Worker   unsigned char const *const end = data->d_buf + data->d_size;
13044*7304104dSAndroid Build Coastguard Worker 
13045*7304104dSAndroid Build Coastguard Worker   uint64_t count, page_size;
13046*7304104dSAndroid Build Coastguard Worker   if (! buf_read_ulong (core, &ptr, end, &count)
13047*7304104dSAndroid Build Coastguard Worker       || ! buf_read_ulong (core, &ptr, end, &page_size))
13048*7304104dSAndroid Build Coastguard Worker     {
13049*7304104dSAndroid Build Coastguard Worker     fail:
13050*7304104dSAndroid Build Coastguard Worker       printf ("    Not enough data in NT_FILE note.\n");
13051*7304104dSAndroid Build Coastguard Worker       return;
13052*7304104dSAndroid Build Coastguard Worker     }
13053*7304104dSAndroid Build Coastguard Worker 
13054*7304104dSAndroid Build Coastguard Worker   size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
13055*7304104dSAndroid Build Coastguard Worker   uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
13056*7304104dSAndroid Build Coastguard Worker   if (count > maxcount)
13057*7304104dSAndroid Build Coastguard Worker     goto fail;
13058*7304104dSAndroid Build Coastguard Worker 
13059*7304104dSAndroid Build Coastguard Worker   /* Where file names are stored.  */
13060*7304104dSAndroid Build Coastguard Worker   unsigned char const *const fstart = ptr + 3 * count * addrsize;
13061*7304104dSAndroid Build Coastguard Worker   char const *fptr = (char *) fstart;
13062*7304104dSAndroid Build Coastguard Worker 
13063*7304104dSAndroid Build Coastguard Worker   printf ("    %" PRId64 " files:\n", count);
13064*7304104dSAndroid Build Coastguard Worker   for (uint64_t i = 0; i < count; ++i)
13065*7304104dSAndroid Build Coastguard Worker     {
13066*7304104dSAndroid Build Coastguard Worker       uint64_t mstart, mend, moffset;
13067*7304104dSAndroid Build Coastguard Worker       if (! buf_read_ulong (core, &ptr, fstart, &mstart)
13068*7304104dSAndroid Build Coastguard Worker 	  || ! buf_read_ulong (core, &ptr, fstart, &mend)
13069*7304104dSAndroid Build Coastguard Worker 	  || ! buf_read_ulong (core, &ptr, fstart, &moffset))
13070*7304104dSAndroid Build Coastguard Worker 	goto fail;
13071*7304104dSAndroid Build Coastguard Worker 
13072*7304104dSAndroid Build Coastguard Worker       const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
13073*7304104dSAndroid Build Coastguard Worker       if (fnext == NULL)
13074*7304104dSAndroid Build Coastguard Worker 	goto fail;
13075*7304104dSAndroid Build Coastguard Worker 
13076*7304104dSAndroid Build Coastguard Worker       int ct = printf ("      %08" PRIx64 "-%08" PRIx64
13077*7304104dSAndroid Build Coastguard Worker 		       " %08" PRIx64 " %" PRId64,
13078*7304104dSAndroid Build Coastguard Worker 		       mstart, mend, moffset * page_size, mend - mstart);
13079*7304104dSAndroid Build Coastguard Worker       printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
13080*7304104dSAndroid Build Coastguard Worker 
13081*7304104dSAndroid Build Coastguard Worker       fptr = fnext + 1;
13082*7304104dSAndroid Build Coastguard Worker     }
13083*7304104dSAndroid Build Coastguard Worker }
13084*7304104dSAndroid Build Coastguard Worker 
13085*7304104dSAndroid Build Coastguard Worker static void
handle_core_note(Ebl * ebl,const GElf_Nhdr * nhdr,const char * name,const void * desc)13086*7304104dSAndroid Build Coastguard Worker handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
13087*7304104dSAndroid Build Coastguard Worker 		  const char *name, const void *desc)
13088*7304104dSAndroid Build Coastguard Worker {
13089*7304104dSAndroid Build Coastguard Worker   GElf_Word regs_offset;
13090*7304104dSAndroid Build Coastguard Worker   size_t nregloc;
13091*7304104dSAndroid Build Coastguard Worker   const Ebl_Register_Location *reglocs;
13092*7304104dSAndroid Build Coastguard Worker   size_t nitems;
13093*7304104dSAndroid Build Coastguard Worker   const Ebl_Core_Item *items;
13094*7304104dSAndroid Build Coastguard Worker 
13095*7304104dSAndroid Build Coastguard Worker   if (! ebl_core_note (ebl, nhdr, name, desc,
13096*7304104dSAndroid Build Coastguard Worker 		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
13097*7304104dSAndroid Build Coastguard Worker     return;
13098*7304104dSAndroid Build Coastguard Worker 
13099*7304104dSAndroid Build Coastguard Worker   /* Pass 0 for DESCSZ when there are registers in the note,
13100*7304104dSAndroid Build Coastguard Worker      so that the ITEMS array does not describe the whole thing.
13101*7304104dSAndroid Build Coastguard Worker      For non-register notes, the actual descsz might be a multiple
13102*7304104dSAndroid Build Coastguard Worker      of the unit size, not just exactly the unit size.  */
13103*7304104dSAndroid Build Coastguard Worker   unsigned int colno = handle_core_items (ebl->elf, desc,
13104*7304104dSAndroid Build Coastguard Worker 					  nregloc == 0 ? nhdr->n_descsz : 0,
13105*7304104dSAndroid Build Coastguard Worker 					  items, nitems);
13106*7304104dSAndroid Build Coastguard Worker   if (colno != 0)
13107*7304104dSAndroid Build Coastguard Worker     putchar_unlocked ('\n');
13108*7304104dSAndroid Build Coastguard Worker 
13109*7304104dSAndroid Build Coastguard Worker   colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
13110*7304104dSAndroid Build Coastguard Worker 				 reglocs, nregloc);
13111*7304104dSAndroid Build Coastguard Worker   if (colno != 0)
13112*7304104dSAndroid Build Coastguard Worker     putchar_unlocked ('\n');
13113*7304104dSAndroid Build Coastguard Worker }
13114*7304104dSAndroid Build Coastguard Worker 
13115*7304104dSAndroid Build Coastguard Worker static void
handle_notes_data(Ebl * ebl,const GElf_Ehdr * ehdr,GElf_Off start,Elf_Data * data)13116*7304104dSAndroid Build Coastguard Worker handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
13117*7304104dSAndroid Build Coastguard Worker 		   GElf_Off start, Elf_Data *data)
13118*7304104dSAndroid Build Coastguard Worker {
13119*7304104dSAndroid Build Coastguard Worker   fputs_unlocked (_("  Owner          Data size  Type\n"), stdout);
13120*7304104dSAndroid Build Coastguard Worker 
13121*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
13122*7304104dSAndroid Build Coastguard Worker     goto bad_note;
13123*7304104dSAndroid Build Coastguard Worker 
13124*7304104dSAndroid Build Coastguard Worker   size_t offset = 0;
13125*7304104dSAndroid Build Coastguard Worker   GElf_Nhdr nhdr;
13126*7304104dSAndroid Build Coastguard Worker   size_t name_offset;
13127*7304104dSAndroid Build Coastguard Worker   size_t desc_offset;
13128*7304104dSAndroid Build Coastguard Worker   while (offset < data->d_size
13129*7304104dSAndroid Build Coastguard Worker 	 && (offset = gelf_getnote (data, offset,
13130*7304104dSAndroid Build Coastguard Worker 				    &nhdr, &name_offset, &desc_offset)) > 0)
13131*7304104dSAndroid Build Coastguard Worker     {
13132*7304104dSAndroid Build Coastguard Worker       const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
13133*7304104dSAndroid Build Coastguard Worker       const char *desc = data->d_buf + desc_offset;
13134*7304104dSAndroid Build Coastguard Worker 
13135*7304104dSAndroid Build Coastguard Worker       /* GNU Build Attributes are weird, they store most of their data
13136*7304104dSAndroid Build Coastguard Worker 	 into the owner name field.  Extract just the owner name
13137*7304104dSAndroid Build Coastguard Worker 	 prefix here, then use the rest later as data.  */
13138*7304104dSAndroid Build Coastguard Worker       bool is_gnu_build_attr
13139*7304104dSAndroid Build Coastguard Worker 	= startswith (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX);
13140*7304104dSAndroid Build Coastguard Worker       const char *print_name = (is_gnu_build_attr
13141*7304104dSAndroid Build Coastguard Worker 				? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
13142*7304104dSAndroid Build Coastguard Worker       size_t print_namesz = (is_gnu_build_attr
13143*7304104dSAndroid Build Coastguard Worker 			     ? strlen (print_name) : nhdr.n_namesz);
13144*7304104dSAndroid Build Coastguard Worker 
13145*7304104dSAndroid Build Coastguard Worker       char buf[100];
13146*7304104dSAndroid Build Coastguard Worker       char buf2[100];
13147*7304104dSAndroid Build Coastguard Worker       printf (_("  %-13.*s  %9" PRId32 "  %s\n"),
13148*7304104dSAndroid Build Coastguard Worker 	      (int) print_namesz, print_name, nhdr.n_descsz,
13149*7304104dSAndroid Build Coastguard Worker 	      ehdr->e_type == ET_CORE
13150*7304104dSAndroid Build Coastguard Worker 	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
13151*7304104dSAndroid Build Coastguard Worker 					 buf, sizeof (buf))
13152*7304104dSAndroid Build Coastguard Worker 	      : ebl_object_note_type_name (ebl, name, nhdr.n_type,
13153*7304104dSAndroid Build Coastguard Worker 					   nhdr.n_descsz,
13154*7304104dSAndroid Build Coastguard Worker 					   buf2, sizeof (buf2)));
13155*7304104dSAndroid Build Coastguard Worker 
13156*7304104dSAndroid Build Coastguard Worker       /* Filter out invalid entries.  */
13157*7304104dSAndroid Build Coastguard Worker       if (memchr (name, '\0', nhdr.n_namesz) != NULL
13158*7304104dSAndroid Build Coastguard Worker 	  /* XXX For now help broken Linux kernels.  */
13159*7304104dSAndroid Build Coastguard Worker 	  || 1)
13160*7304104dSAndroid Build Coastguard Worker 	{
13161*7304104dSAndroid Build Coastguard Worker 	  if (ehdr->e_type == ET_CORE)
13162*7304104dSAndroid Build Coastguard Worker 	    {
13163*7304104dSAndroid Build Coastguard Worker 	      if (nhdr.n_type == NT_AUXV
13164*7304104dSAndroid Build Coastguard Worker 		  && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
13165*7304104dSAndroid Build Coastguard Worker 		      || (nhdr.n_namesz == 5 && name[4] == '\0'))
13166*7304104dSAndroid Build Coastguard Worker 		  && !memcmp (name, "CORE", 4))
13167*7304104dSAndroid Build Coastguard Worker 		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
13168*7304104dSAndroid Build Coastguard Worker 				  start + desc_offset);
13169*7304104dSAndroid Build Coastguard Worker 	      else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
13170*7304104dSAndroid Build Coastguard Worker 		switch (nhdr.n_type)
13171*7304104dSAndroid Build Coastguard Worker 		  {
13172*7304104dSAndroid Build Coastguard Worker 		  case NT_SIGINFO:
13173*7304104dSAndroid Build Coastguard Worker 		    handle_siginfo_note (ebl->elf, nhdr.n_descsz,
13174*7304104dSAndroid Build Coastguard Worker 					 start + desc_offset);
13175*7304104dSAndroid Build Coastguard Worker 		    break;
13176*7304104dSAndroid Build Coastguard Worker 
13177*7304104dSAndroid Build Coastguard Worker 		  case NT_FILE:
13178*7304104dSAndroid Build Coastguard Worker 		    handle_file_note (ebl->elf, nhdr.n_descsz,
13179*7304104dSAndroid Build Coastguard Worker 				      start + desc_offset);
13180*7304104dSAndroid Build Coastguard Worker 		    break;
13181*7304104dSAndroid Build Coastguard Worker 
13182*7304104dSAndroid Build Coastguard Worker 		  default:
13183*7304104dSAndroid Build Coastguard Worker 		    handle_core_note (ebl, &nhdr, name, desc);
13184*7304104dSAndroid Build Coastguard Worker 		  }
13185*7304104dSAndroid Build Coastguard Worker 	      else
13186*7304104dSAndroid Build Coastguard Worker 		handle_core_note (ebl, &nhdr, name, desc);
13187*7304104dSAndroid Build Coastguard Worker 	    }
13188*7304104dSAndroid Build Coastguard Worker 	  else
13189*7304104dSAndroid Build Coastguard Worker 	    ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
13190*7304104dSAndroid Build Coastguard Worker 			     nhdr.n_descsz, desc);
13191*7304104dSAndroid Build Coastguard Worker 	}
13192*7304104dSAndroid Build Coastguard Worker     }
13193*7304104dSAndroid Build Coastguard Worker 
13194*7304104dSAndroid Build Coastguard Worker   if (offset == data->d_size)
13195*7304104dSAndroid Build Coastguard Worker     return;
13196*7304104dSAndroid Build Coastguard Worker 
13197*7304104dSAndroid Build Coastguard Worker  bad_note:
13198*7304104dSAndroid Build Coastguard Worker   error (0, 0,
13199*7304104dSAndroid Build Coastguard Worker 	 _("cannot get content of note: %s"),
13200*7304104dSAndroid Build Coastguard Worker 	 data != NULL ? "garbage data" : elf_errmsg (-1));
13201*7304104dSAndroid Build Coastguard Worker }
13202*7304104dSAndroid Build Coastguard Worker 
13203*7304104dSAndroid Build Coastguard Worker static void
handle_notes(Ebl * ebl,GElf_Ehdr * ehdr)13204*7304104dSAndroid Build Coastguard Worker handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
13205*7304104dSAndroid Build Coastguard Worker {
13206*7304104dSAndroid Build Coastguard Worker   /* If we have section headers, just look for SHT_NOTE sections.
13207*7304104dSAndroid Build Coastguard Worker      In a debuginfo file, the program headers are not reliable.  */
13208*7304104dSAndroid Build Coastguard Worker   if (shnum != 0)
13209*7304104dSAndroid Build Coastguard Worker     {
13210*7304104dSAndroid Build Coastguard Worker       /* Get the section header string table index.  */
13211*7304104dSAndroid Build Coastguard Worker       size_t shstrndx;
13212*7304104dSAndroid Build Coastguard Worker       if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
13213*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get section header string table index"));
13214*7304104dSAndroid Build Coastguard Worker 
13215*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn = NULL;
13216*7304104dSAndroid Build Coastguard Worker       while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
13217*7304104dSAndroid Build Coastguard Worker 	{
13218*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr shdr_mem;
13219*7304104dSAndroid Build Coastguard Worker 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
13220*7304104dSAndroid Build Coastguard Worker 
13221*7304104dSAndroid Build Coastguard Worker 	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
13222*7304104dSAndroid Build Coastguard Worker 	    /* Not what we are looking for.  */
13223*7304104dSAndroid Build Coastguard Worker 	    continue;
13224*7304104dSAndroid Build Coastguard Worker 
13225*7304104dSAndroid Build Coastguard Worker 	  if (notes_section != NULL)
13226*7304104dSAndroid Build Coastguard Worker 	    {
13227*7304104dSAndroid Build Coastguard Worker 	      char *sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
13228*7304104dSAndroid Build Coastguard Worker 	      if (sname == NULL || strcmp (sname, notes_section) != 0)
13229*7304104dSAndroid Build Coastguard Worker 		continue;
13230*7304104dSAndroid Build Coastguard Worker 	    }
13231*7304104dSAndroid Build Coastguard Worker 
13232*7304104dSAndroid Build Coastguard Worker 	  printf (_("\
13233*7304104dSAndroid Build Coastguard Worker \nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
13234*7304104dSAndroid Build Coastguard Worker 		  elf_ndxscn (scn),
13235*7304104dSAndroid Build Coastguard Worker 		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
13236*7304104dSAndroid Build Coastguard Worker 		  shdr->sh_size, shdr->sh_offset);
13237*7304104dSAndroid Build Coastguard Worker 
13238*7304104dSAndroid Build Coastguard Worker 	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
13239*7304104dSAndroid Build Coastguard Worker 			     elf_getdata (scn, NULL));
13240*7304104dSAndroid Build Coastguard Worker 	}
13241*7304104dSAndroid Build Coastguard Worker       return;
13242*7304104dSAndroid Build Coastguard Worker     }
13243*7304104dSAndroid Build Coastguard Worker 
13244*7304104dSAndroid Build Coastguard Worker   /* We have to look through the program header to find the note
13245*7304104dSAndroid Build Coastguard Worker      sections.  There can be more than one.  */
13246*7304104dSAndroid Build Coastguard Worker   for (size_t cnt = 0; cnt < phnum; ++cnt)
13247*7304104dSAndroid Build Coastguard Worker     {
13248*7304104dSAndroid Build Coastguard Worker       GElf_Phdr mem;
13249*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
13250*7304104dSAndroid Build Coastguard Worker 
13251*7304104dSAndroid Build Coastguard Worker       if (phdr == NULL || phdr->p_type != PT_NOTE)
13252*7304104dSAndroid Build Coastguard Worker 	/* Not what we are looking for.  */
13253*7304104dSAndroid Build Coastguard Worker 	continue;
13254*7304104dSAndroid Build Coastguard Worker 
13255*7304104dSAndroid Build Coastguard Worker       printf (_("\
13256*7304104dSAndroid Build Coastguard Worker \nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
13257*7304104dSAndroid Build Coastguard Worker 	      phdr->p_filesz, phdr->p_offset);
13258*7304104dSAndroid Build Coastguard Worker 
13259*7304104dSAndroid Build Coastguard Worker       handle_notes_data (ebl, ehdr, phdr->p_offset,
13260*7304104dSAndroid Build Coastguard Worker 			 elf_getdata_rawchunk (ebl->elf,
13261*7304104dSAndroid Build Coastguard Worker 					       phdr->p_offset, phdr->p_filesz,
13262*7304104dSAndroid Build Coastguard Worker 					       (phdr->p_align == 8
13263*7304104dSAndroid Build Coastguard Worker 						? ELF_T_NHDR8 : ELF_T_NHDR)));
13264*7304104dSAndroid Build Coastguard Worker     }
13265*7304104dSAndroid Build Coastguard Worker }
13266*7304104dSAndroid Build Coastguard Worker 
13267*7304104dSAndroid Build Coastguard Worker 
13268*7304104dSAndroid Build Coastguard Worker static void
hex_dump(const uint8_t * data,size_t len)13269*7304104dSAndroid Build Coastguard Worker hex_dump (const uint8_t *data, size_t len)
13270*7304104dSAndroid Build Coastguard Worker {
13271*7304104dSAndroid Build Coastguard Worker   size_t pos = 0;
13272*7304104dSAndroid Build Coastguard Worker   while (pos < len)
13273*7304104dSAndroid Build Coastguard Worker     {
13274*7304104dSAndroid Build Coastguard Worker       printf ("  0x%08zx ", pos);
13275*7304104dSAndroid Build Coastguard Worker 
13276*7304104dSAndroid Build Coastguard Worker       const size_t chunk = MIN (len - pos, 16);
13277*7304104dSAndroid Build Coastguard Worker 
13278*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < chunk; ++i)
13279*7304104dSAndroid Build Coastguard Worker 	if (i % 4 == 3)
13280*7304104dSAndroid Build Coastguard Worker 	  printf ("%02x ", data[pos + i]);
13281*7304104dSAndroid Build Coastguard Worker 	else
13282*7304104dSAndroid Build Coastguard Worker 	  printf ("%02x", data[pos + i]);
13283*7304104dSAndroid Build Coastguard Worker 
13284*7304104dSAndroid Build Coastguard Worker       if (chunk < 16)
13285*7304104dSAndroid Build Coastguard Worker 	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
13286*7304104dSAndroid Build Coastguard Worker 
13287*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < chunk; ++i)
13288*7304104dSAndroid Build Coastguard Worker 	{
13289*7304104dSAndroid Build Coastguard Worker 	  unsigned char b = data[pos + i];
13290*7304104dSAndroid Build Coastguard Worker 	  printf ("%c", isprint (b) ? b : '.');
13291*7304104dSAndroid Build Coastguard Worker 	}
13292*7304104dSAndroid Build Coastguard Worker 
13293*7304104dSAndroid Build Coastguard Worker       putchar ('\n');
13294*7304104dSAndroid Build Coastguard Worker       pos += chunk;
13295*7304104dSAndroid Build Coastguard Worker     }
13296*7304104dSAndroid Build Coastguard Worker }
13297*7304104dSAndroid Build Coastguard Worker 
13298*7304104dSAndroid Build Coastguard Worker static void
dump_data_section(Elf_Scn * scn,const GElf_Shdr * shdr,const char * name)13299*7304104dSAndroid Build Coastguard Worker dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
13300*7304104dSAndroid Build Coastguard Worker {
13301*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
13302*7304104dSAndroid Build Coastguard Worker     printf (_("\nSection [%zu] '%s' has no data to dump.\n"),
13303*7304104dSAndroid Build Coastguard Worker 	    elf_ndxscn (scn), name);
13304*7304104dSAndroid Build Coastguard Worker   else
13305*7304104dSAndroid Build Coastguard Worker     {
13306*7304104dSAndroid Build Coastguard Worker       if (print_decompress)
13307*7304104dSAndroid Build Coastguard Worker 	{
13308*7304104dSAndroid Build Coastguard Worker 	  /* We try to decompress the section, but keep the old shdr around
13309*7304104dSAndroid Build Coastguard Worker 	     so we can show both the original shdr size and the uncompressed
13310*7304104dSAndroid Build Coastguard Worker 	     data size.   */
13311*7304104dSAndroid Build Coastguard Worker 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
13312*7304104dSAndroid Build Coastguard Worker 	    {
13313*7304104dSAndroid Build Coastguard Worker 	      if (elf_compress (scn, 0, 0) < 0)
13314*7304104dSAndroid Build Coastguard Worker 		printf ("WARNING: %s [%zd]\n",
13315*7304104dSAndroid Build Coastguard Worker 			_("Couldn't uncompress section"),
13316*7304104dSAndroid Build Coastguard Worker 			elf_ndxscn (scn));
13317*7304104dSAndroid Build Coastguard Worker 	    }
13318*7304104dSAndroid Build Coastguard Worker 	  else if (startswith (name, ".zdebug"))
13319*7304104dSAndroid Build Coastguard Worker 	    {
13320*7304104dSAndroid Build Coastguard Worker 	      if (elf_compress_gnu (scn, 0, 0) < 0)
13321*7304104dSAndroid Build Coastguard Worker 		printf ("WARNING: %s [%zd]\n",
13322*7304104dSAndroid Build Coastguard Worker 			_("Couldn't uncompress section"),
13323*7304104dSAndroid Build Coastguard Worker 			elf_ndxscn (scn));
13324*7304104dSAndroid Build Coastguard Worker 	    }
13325*7304104dSAndroid Build Coastguard Worker 	}
13326*7304104dSAndroid Build Coastguard Worker 
13327*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_rawdata (scn, NULL);
13328*7304104dSAndroid Build Coastguard Worker       if (data == NULL)
13329*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("cannot get data for section [%zu] '%s': %s"),
13330*7304104dSAndroid Build Coastguard Worker 	       elf_ndxscn (scn), name, elf_errmsg (-1));
13331*7304104dSAndroid Build Coastguard Worker       else
13332*7304104dSAndroid Build Coastguard Worker 	{
13333*7304104dSAndroid Build Coastguard Worker 	  if (data->d_size == shdr->sh_size)
13334*7304104dSAndroid Build Coastguard Worker 	    printf (_("\nHex dump of section [%zu] '%s', %" PRIu64
13335*7304104dSAndroid Build Coastguard Worker 			     " bytes at offset %#0" PRIx64 ":\n"),
13336*7304104dSAndroid Build Coastguard Worker 		    elf_ndxscn (scn), name,
13337*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_size, shdr->sh_offset);
13338*7304104dSAndroid Build Coastguard Worker 	  else
13339*7304104dSAndroid Build Coastguard Worker 	    printf (_("\nHex dump of section [%zu] '%s', %" PRIu64
13340*7304104dSAndroid Build Coastguard Worker 			     " bytes (%zd uncompressed) at offset %#0"
13341*7304104dSAndroid Build Coastguard Worker 			     PRIx64 ":\n"),
13342*7304104dSAndroid Build Coastguard Worker 		    elf_ndxscn (scn), name,
13343*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_size, data->d_size, shdr->sh_offset);
13344*7304104dSAndroid Build Coastguard Worker 	  hex_dump (data->d_buf, data->d_size);
13345*7304104dSAndroid Build Coastguard Worker 	}
13346*7304104dSAndroid Build Coastguard Worker     }
13347*7304104dSAndroid Build Coastguard Worker }
13348*7304104dSAndroid Build Coastguard Worker 
13349*7304104dSAndroid Build Coastguard Worker static void
print_string_section(Elf_Scn * scn,const GElf_Shdr * shdr,const char * name)13350*7304104dSAndroid Build Coastguard Worker print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
13351*7304104dSAndroid Build Coastguard Worker {
13352*7304104dSAndroid Build Coastguard Worker   if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
13353*7304104dSAndroid Build Coastguard Worker     printf (_("\nSection [%zu] '%s' has no strings to dump.\n"),
13354*7304104dSAndroid Build Coastguard Worker 	    elf_ndxscn (scn), name);
13355*7304104dSAndroid Build Coastguard Worker   else
13356*7304104dSAndroid Build Coastguard Worker     {
13357*7304104dSAndroid Build Coastguard Worker       if (print_decompress)
13358*7304104dSAndroid Build Coastguard Worker 	{
13359*7304104dSAndroid Build Coastguard Worker 	  /* We try to decompress the section, but keep the old shdr around
13360*7304104dSAndroid Build Coastguard Worker 	     so we can show both the original shdr size and the uncompressed
13361*7304104dSAndroid Build Coastguard Worker 	     data size.  */
13362*7304104dSAndroid Build Coastguard Worker 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
13363*7304104dSAndroid Build Coastguard Worker 	    {
13364*7304104dSAndroid Build Coastguard Worker 	      if (elf_compress (scn, 0, 0) < 0)
13365*7304104dSAndroid Build Coastguard Worker 		printf ("WARNING: %s [%zd]\n",
13366*7304104dSAndroid Build Coastguard Worker 			_("Couldn't uncompress section"),
13367*7304104dSAndroid Build Coastguard Worker 			elf_ndxscn (scn));
13368*7304104dSAndroid Build Coastguard Worker 	    }
13369*7304104dSAndroid Build Coastguard Worker 	  else if (startswith (name, ".zdebug"))
13370*7304104dSAndroid Build Coastguard Worker 	    {
13371*7304104dSAndroid Build Coastguard Worker 	      if (elf_compress_gnu (scn, 0, 0) < 0)
13372*7304104dSAndroid Build Coastguard Worker 		printf ("WARNING: %s [%zd]\n",
13373*7304104dSAndroid Build Coastguard Worker 			_("Couldn't uncompress section"),
13374*7304104dSAndroid Build Coastguard Worker 			elf_ndxscn (scn));
13375*7304104dSAndroid Build Coastguard Worker 	    }
13376*7304104dSAndroid Build Coastguard Worker 	}
13377*7304104dSAndroid Build Coastguard Worker 
13378*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_rawdata (scn, NULL);
13379*7304104dSAndroid Build Coastguard Worker       if (data == NULL)
13380*7304104dSAndroid Build Coastguard Worker 	error (0, 0, _("cannot get data for section [%zu] '%s': %s"),
13381*7304104dSAndroid Build Coastguard Worker 	       elf_ndxscn (scn), name, elf_errmsg (-1));
13382*7304104dSAndroid Build Coastguard Worker       else
13383*7304104dSAndroid Build Coastguard Worker 	{
13384*7304104dSAndroid Build Coastguard Worker 	  if (data->d_size == shdr->sh_size)
13385*7304104dSAndroid Build Coastguard Worker 	    printf (_("\nString section [%zu] '%s' contains %" PRIu64
13386*7304104dSAndroid Build Coastguard Worker 			     " bytes at offset %#0" PRIx64 ":\n"),
13387*7304104dSAndroid Build Coastguard Worker 		    elf_ndxscn (scn), name,
13388*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_size, shdr->sh_offset);
13389*7304104dSAndroid Build Coastguard Worker 	  else
13390*7304104dSAndroid Build Coastguard Worker 	    printf (_("\nString section [%zu] '%s' contains %" PRIu64
13391*7304104dSAndroid Build Coastguard Worker 			     " bytes (%zd uncompressed) at offset %#0"
13392*7304104dSAndroid Build Coastguard Worker 			     PRIx64 ":\n"),
13393*7304104dSAndroid Build Coastguard Worker 		    elf_ndxscn (scn), name,
13394*7304104dSAndroid Build Coastguard Worker 		    shdr->sh_size, data->d_size, shdr->sh_offset);
13395*7304104dSAndroid Build Coastguard Worker 
13396*7304104dSAndroid Build Coastguard Worker 	  const char *start = data->d_buf;
13397*7304104dSAndroid Build Coastguard Worker 	  const char *const limit = start + data->d_size;
13398*7304104dSAndroid Build Coastguard Worker 	  do
13399*7304104dSAndroid Build Coastguard Worker 	    {
13400*7304104dSAndroid Build Coastguard Worker 	      const char *end = memchr (start, '\0', limit - start);
13401*7304104dSAndroid Build Coastguard Worker 	      const size_t pos = start - (const char *) data->d_buf;
13402*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (end == NULL))
13403*7304104dSAndroid Build Coastguard Worker 		{
13404*7304104dSAndroid Build Coastguard Worker 		  printf ("  [%6zx]- %.*s\n",
13405*7304104dSAndroid Build Coastguard Worker 			  pos, (int) (limit - start), start);
13406*7304104dSAndroid Build Coastguard Worker 		  break;
13407*7304104dSAndroid Build Coastguard Worker 		}
13408*7304104dSAndroid Build Coastguard Worker 	      printf ("  [%6zx]  %s\n", pos, start);
13409*7304104dSAndroid Build Coastguard Worker 	      start = end + 1;
13410*7304104dSAndroid Build Coastguard Worker 	    } while (start < limit);
13411*7304104dSAndroid Build Coastguard Worker 	}
13412*7304104dSAndroid Build Coastguard Worker     }
13413*7304104dSAndroid Build Coastguard Worker }
13414*7304104dSAndroid Build Coastguard Worker 
13415*7304104dSAndroid Build Coastguard Worker static void
for_each_section_argument(Elf * elf,const struct section_argument * list,void (* dump)(Elf_Scn * scn,const GElf_Shdr * shdr,const char * name))13416*7304104dSAndroid Build Coastguard Worker for_each_section_argument (Elf *elf, const struct section_argument *list,
13417*7304104dSAndroid Build Coastguard Worker 			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
13418*7304104dSAndroid Build Coastguard Worker 					 const char *name))
13419*7304104dSAndroid Build Coastguard Worker {
13420*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
13421*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
13422*7304104dSAndroid Build Coastguard Worker   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
13423*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
13424*7304104dSAndroid Build Coastguard Worker 
13425*7304104dSAndroid Build Coastguard Worker   for (const struct section_argument *a = list; a != NULL; a = a->next)
13426*7304104dSAndroid Build Coastguard Worker     {
13427*7304104dSAndroid Build Coastguard Worker       Elf_Scn *scn;
13428*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
13429*7304104dSAndroid Build Coastguard Worker       const char *name = NULL;
13430*7304104dSAndroid Build Coastguard Worker 
13431*7304104dSAndroid Build Coastguard Worker       char *endp = NULL;
13432*7304104dSAndroid Build Coastguard Worker       unsigned long int shndx = strtoul (a->arg, &endp, 0);
13433*7304104dSAndroid Build Coastguard Worker       if (endp != a->arg && *endp == '\0')
13434*7304104dSAndroid Build Coastguard Worker 	{
13435*7304104dSAndroid Build Coastguard Worker 	  scn = elf_getscn (elf, shndx);
13436*7304104dSAndroid Build Coastguard Worker 	  if (scn == NULL)
13437*7304104dSAndroid Build Coastguard Worker 	    {
13438*7304104dSAndroid Build Coastguard Worker 	      error (0, 0, _("\nsection [%lu] does not exist"), shndx);
13439*7304104dSAndroid Build Coastguard Worker 	      continue;
13440*7304104dSAndroid Build Coastguard Worker 	    }
13441*7304104dSAndroid Build Coastguard Worker 
13442*7304104dSAndroid Build Coastguard Worker 	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
13443*7304104dSAndroid Build Coastguard Worker 	    error_exit (0, _("cannot get section header: %s"),
13444*7304104dSAndroid Build Coastguard Worker 			elf_errmsg (-1));
13445*7304104dSAndroid Build Coastguard Worker 	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
13446*7304104dSAndroid Build Coastguard Worker 	  (*dump) (scn, &shdr_mem, name);
13447*7304104dSAndroid Build Coastguard Worker 	}
13448*7304104dSAndroid Build Coastguard Worker       else
13449*7304104dSAndroid Build Coastguard Worker 	{
13450*7304104dSAndroid Build Coastguard Worker 	  /* Need to look up the section by name.  */
13451*7304104dSAndroid Build Coastguard Worker 	  scn = NULL;
13452*7304104dSAndroid Build Coastguard Worker 	  bool found = false;
13453*7304104dSAndroid Build Coastguard Worker 	  while ((scn = elf_nextscn (elf, scn)) != NULL)
13454*7304104dSAndroid Build Coastguard Worker 	    {
13455*7304104dSAndroid Build Coastguard Worker 	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
13456*7304104dSAndroid Build Coastguard Worker 		continue;
13457*7304104dSAndroid Build Coastguard Worker 	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
13458*7304104dSAndroid Build Coastguard Worker 	      if (name == NULL)
13459*7304104dSAndroid Build Coastguard Worker 		continue;
13460*7304104dSAndroid Build Coastguard Worker 	      if (!strcmp (name, a->arg))
13461*7304104dSAndroid Build Coastguard Worker 		{
13462*7304104dSAndroid Build Coastguard Worker 		  found = true;
13463*7304104dSAndroid Build Coastguard Worker 		  (*dump) (scn, &shdr_mem, name);
13464*7304104dSAndroid Build Coastguard Worker 		}
13465*7304104dSAndroid Build Coastguard Worker 	    }
13466*7304104dSAndroid Build Coastguard Worker 
13467*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (!found) && !a->implicit)
13468*7304104dSAndroid Build Coastguard Worker 	    error (0, 0, _("\nsection '%s' does not exist"), a->arg);
13469*7304104dSAndroid Build Coastguard Worker 	}
13470*7304104dSAndroid Build Coastguard Worker     }
13471*7304104dSAndroid Build Coastguard Worker }
13472*7304104dSAndroid Build Coastguard Worker 
13473*7304104dSAndroid Build Coastguard Worker static void
dump_data(Ebl * ebl)13474*7304104dSAndroid Build Coastguard Worker dump_data (Ebl *ebl)
13475*7304104dSAndroid Build Coastguard Worker {
13476*7304104dSAndroid Build Coastguard Worker   for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
13477*7304104dSAndroid Build Coastguard Worker }
13478*7304104dSAndroid Build Coastguard Worker 
13479*7304104dSAndroid Build Coastguard Worker static void
dump_strings(Ebl * ebl)13480*7304104dSAndroid Build Coastguard Worker dump_strings (Ebl *ebl)
13481*7304104dSAndroid Build Coastguard Worker {
13482*7304104dSAndroid Build Coastguard Worker   for_each_section_argument (ebl->elf, string_sections, &print_string_section);
13483*7304104dSAndroid Build Coastguard Worker }
13484*7304104dSAndroid Build Coastguard Worker 
13485*7304104dSAndroid Build Coastguard Worker static void
print_strings(Ebl * ebl)13486*7304104dSAndroid Build Coastguard Worker print_strings (Ebl *ebl)
13487*7304104dSAndroid Build Coastguard Worker {
13488*7304104dSAndroid Build Coastguard Worker   /* Get the section header string table index.  */
13489*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
13490*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
13491*7304104dSAndroid Build Coastguard Worker     error_exit (0, _("cannot get section header string table index"));
13492*7304104dSAndroid Build Coastguard Worker 
13493*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn;
13494*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
13495*7304104dSAndroid Build Coastguard Worker   const char *name;
13496*7304104dSAndroid Build Coastguard Worker   scn = NULL;
13497*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
13498*7304104dSAndroid Build Coastguard Worker     {
13499*7304104dSAndroid Build Coastguard Worker       if (gelf_getshdr (scn, &shdr_mem) == NULL)
13500*7304104dSAndroid Build Coastguard Worker 	continue;
13501*7304104dSAndroid Build Coastguard Worker 
13502*7304104dSAndroid Build Coastguard Worker       if (shdr_mem.sh_type != SHT_PROGBITS
13503*7304104dSAndroid Build Coastguard Worker 	  || !(shdr_mem.sh_flags & SHF_STRINGS))
13504*7304104dSAndroid Build Coastguard Worker 	continue;
13505*7304104dSAndroid Build Coastguard Worker 
13506*7304104dSAndroid Build Coastguard Worker       name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
13507*7304104dSAndroid Build Coastguard Worker       if (name == NULL)
13508*7304104dSAndroid Build Coastguard Worker 	continue;
13509*7304104dSAndroid Build Coastguard Worker 
13510*7304104dSAndroid Build Coastguard Worker       print_string_section (scn, &shdr_mem, name);
13511*7304104dSAndroid Build Coastguard Worker     }
13512*7304104dSAndroid Build Coastguard Worker }
13513*7304104dSAndroid Build Coastguard Worker 
13514*7304104dSAndroid Build Coastguard Worker static void
dump_archive_index(Elf * elf,const char * fname)13515*7304104dSAndroid Build Coastguard Worker dump_archive_index (Elf *elf, const char *fname)
13516*7304104dSAndroid Build Coastguard Worker {
13517*7304104dSAndroid Build Coastguard Worker   size_t narsym;
13518*7304104dSAndroid Build Coastguard Worker   const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
13519*7304104dSAndroid Build Coastguard Worker   if (arsym == NULL)
13520*7304104dSAndroid Build Coastguard Worker     {
13521*7304104dSAndroid Build Coastguard Worker       int result = elf_errno ();
13522*7304104dSAndroid Build Coastguard Worker       if (unlikely (result != ELF_E_NO_INDEX))
13523*7304104dSAndroid Build Coastguard Worker 	error_exit (0, _("cannot get symbol index of archive '%s': %s"),
13524*7304104dSAndroid Build Coastguard Worker 		    fname, elf_errmsg (result));
13525*7304104dSAndroid Build Coastguard Worker       else
13526*7304104dSAndroid Build Coastguard Worker 	printf (_("\nArchive '%s' has no symbol index\n"), fname);
13527*7304104dSAndroid Build Coastguard Worker       return;
13528*7304104dSAndroid Build Coastguard Worker     }
13529*7304104dSAndroid Build Coastguard Worker 
13530*7304104dSAndroid Build Coastguard Worker   printf (_("\nIndex of archive '%s' has %zu entries:\n"),
13531*7304104dSAndroid Build Coastguard Worker 	  fname, narsym);
13532*7304104dSAndroid Build Coastguard Worker 
13533*7304104dSAndroid Build Coastguard Worker   size_t as_off = 0;
13534*7304104dSAndroid Build Coastguard Worker   for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
13535*7304104dSAndroid Build Coastguard Worker     {
13536*7304104dSAndroid Build Coastguard Worker       if (s->as_off != as_off)
13537*7304104dSAndroid Build Coastguard Worker 	{
13538*7304104dSAndroid Build Coastguard Worker 	  as_off = s->as_off;
13539*7304104dSAndroid Build Coastguard Worker 
13540*7304104dSAndroid Build Coastguard Worker 	  Elf *subelf = NULL;
13541*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (elf_rand (elf, as_off) == 0)
13542*7304104dSAndroid Build Coastguard Worker 	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
13543*7304104dSAndroid Build Coastguard Worker 			   == NULL))
13544*7304104dSAndroid Build Coastguard Worker #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
13545*7304104dSAndroid Build Coastguard Worker 	    while (1)
13546*7304104dSAndroid Build Coastguard Worker #endif
13547*7304104dSAndroid Build Coastguard Worker 	      error_exit (0,
13548*7304104dSAndroid Build Coastguard Worker 			  _("cannot extract member at offset %zu in '%s': %s"),
13549*7304104dSAndroid Build Coastguard Worker 			  as_off, fname, elf_errmsg (-1));
13550*7304104dSAndroid Build Coastguard Worker 
13551*7304104dSAndroid Build Coastguard Worker 	  const Elf_Arhdr *h = elf_getarhdr (subelf);
13552*7304104dSAndroid Build Coastguard Worker 
13553*7304104dSAndroid Build Coastguard Worker 	  printf (_("Archive member '%s' contains:\n"), h->ar_name);
13554*7304104dSAndroid Build Coastguard Worker 
13555*7304104dSAndroid Build Coastguard Worker 	  elf_end (subelf);
13556*7304104dSAndroid Build Coastguard Worker 	}
13557*7304104dSAndroid Build Coastguard Worker 
13558*7304104dSAndroid Build Coastguard Worker       printf ("\t%s\n", s->as_name);
13559*7304104dSAndroid Build Coastguard Worker     }
13560*7304104dSAndroid Build Coastguard Worker }
13561*7304104dSAndroid Build Coastguard Worker 
13562*7304104dSAndroid Build Coastguard Worker #include "debugpred.h"
13563