1*7304104dSAndroid Build Coastguard Worker /* Locate source files and line information for given addresses
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2005-2010, 2012, 2013, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker Copyright (C) 2022, 2023 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2005.
6*7304104dSAndroid Build Coastguard Worker
7*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
8*7304104dSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
9*7304104dSAndroid Build Coastguard Worker the Free Software Foundation; either version 3 of the License, or
10*7304104dSAndroid Build Coastguard Worker (at your option) any later version.
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
13*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
14*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*7304104dSAndroid Build Coastguard Worker GNU General Public License for more details.
16*7304104dSAndroid Build Coastguard Worker
17*7304104dSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
18*7304104dSAndroid Build Coastguard Worker along with this program. If not, see <http://www.gnu.org/licenses/>. */
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
21*7304104dSAndroid Build Coastguard Worker # include <config.h>
22*7304104dSAndroid Build Coastguard Worker #endif
23*7304104dSAndroid Build Coastguard Worker
24*7304104dSAndroid Build Coastguard Worker #include <argp.h>
25*7304104dSAndroid Build Coastguard Worker #include <assert.h>
26*7304104dSAndroid Build Coastguard Worker #include <errno.h>
27*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
28*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
29*7304104dSAndroid Build Coastguard Worker #include <libdwfl.h>
30*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
31*7304104dSAndroid Build Coastguard Worker #include <locale.h>
32*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
33*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
34*7304104dSAndroid Build Coastguard Worker #include <stdio_ext.h>
35*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
36*7304104dSAndroid Build Coastguard Worker #include <string.h>
37*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker #include <system.h>
40*7304104dSAndroid Build Coastguard Worker #include <printversion.h>
41*7304104dSAndroid Build Coastguard Worker
42*7304104dSAndroid Build Coastguard Worker
43*7304104dSAndroid Build Coastguard Worker /* Name and version of program. */
44*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
45*7304104dSAndroid Build Coastguard Worker
46*7304104dSAndroid Build Coastguard Worker /* Bug report address. */
47*7304104dSAndroid Build Coastguard Worker ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
48*7304104dSAndroid Build Coastguard Worker
49*7304104dSAndroid Build Coastguard Worker
50*7304104dSAndroid Build Coastguard Worker /* Values for the parameters which have no short form. */
51*7304104dSAndroid Build Coastguard Worker #define OPT_DEMANGLER 0x100
52*7304104dSAndroid Build Coastguard Worker #define OPT_PRETTY 0x101 /* 'p' is already used to select the process. */
53*7304104dSAndroid Build Coastguard Worker #define OPT_RELATIVE 0x102 /* 'r' is something else in binutils addr2line. */
54*7304104dSAndroid Build Coastguard Worker
55*7304104dSAndroid Build Coastguard Worker /* Definitions of arguments for argp functions. */
56*7304104dSAndroid Build Coastguard Worker static const struct argp_option options[] =
57*7304104dSAndroid Build Coastguard Worker {
58*7304104dSAndroid Build Coastguard Worker { NULL, 0, NULL, 0, N_("Input format options:"), 2 },
59*7304104dSAndroid Build Coastguard Worker { "section", 'j', "NAME", 0,
60*7304104dSAndroid Build Coastguard Worker N_("Treat addresses as offsets relative to NAME section."), 0 },
61*7304104dSAndroid Build Coastguard Worker
62*7304104dSAndroid Build Coastguard Worker { NULL, 0, NULL, 0, N_("Output format options:"), 3 },
63*7304104dSAndroid Build Coastguard Worker { "addresses", 'a', NULL, 0, N_("Print address before each entry"), 0 },
64*7304104dSAndroid Build Coastguard Worker { "basenames", 's', NULL, 0, N_("Show only base names of source files"), 0 },
65*7304104dSAndroid Build Coastguard Worker { "absolute", 'A', NULL, 0,
66*7304104dSAndroid Build Coastguard Worker N_("Show absolute file names using compilation directory (default)"), 0 },
67*7304104dSAndroid Build Coastguard Worker { "functions", 'f', NULL, 0, N_("Also show function names"), 0 },
68*7304104dSAndroid Build Coastguard Worker { "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 },
69*7304104dSAndroid Build Coastguard Worker { "symbols-sections", 'x', NULL, 0, N_("Also show symbol and the section names"), 0 },
70*7304104dSAndroid Build Coastguard Worker { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
71*7304104dSAndroid Build Coastguard Worker { "inlines", 'i', NULL, 0,
72*7304104dSAndroid Build Coastguard Worker N_("Show all source locations that caused inline expansion of subroutines at the address."),
73*7304104dSAndroid Build Coastguard Worker 0 },
74*7304104dSAndroid Build Coastguard Worker { "demangle", OPT_DEMANGLER, "ARG", OPTION_ARG_OPTIONAL,
75*7304104dSAndroid Build Coastguard Worker N_("Show demangled symbols (ARG is always ignored)"), 0 },
76*7304104dSAndroid Build Coastguard Worker { NULL, 'C', NULL, 0, N_("Show demangled symbols"), 0 },
77*7304104dSAndroid Build Coastguard Worker { "pretty-print", OPT_PRETTY, NULL, 0,
78*7304104dSAndroid Build Coastguard Worker N_("Print all information on one line, and indent inlines"), 0 },
79*7304104dSAndroid Build Coastguard Worker { "relative", OPT_RELATIVE, NULL, 0,
80*7304104dSAndroid Build Coastguard Worker N_("Show relative file names without compilation directory"), 0 },
81*7304104dSAndroid Build Coastguard Worker
82*7304104dSAndroid Build Coastguard Worker { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
83*7304104dSAndroid Build Coastguard Worker /* Unsupported options. */
84*7304104dSAndroid Build Coastguard Worker { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 },
85*7304104dSAndroid Build Coastguard Worker { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 },
86*7304104dSAndroid Build Coastguard Worker { NULL, 0, NULL, 0, NULL, 0 }
87*7304104dSAndroid Build Coastguard Worker };
88*7304104dSAndroid Build Coastguard Worker
89*7304104dSAndroid Build Coastguard Worker /* Short description of program. */
90*7304104dSAndroid Build Coastguard Worker static const char doc[] = N_("\
91*7304104dSAndroid Build Coastguard Worker Locate source files and line information for ADDRs (in a.out by default).");
92*7304104dSAndroid Build Coastguard Worker
93*7304104dSAndroid Build Coastguard Worker /* Strings for arguments in help texts. */
94*7304104dSAndroid Build Coastguard Worker static const char args_doc[] = N_("[ADDR...]");
95*7304104dSAndroid Build Coastguard Worker
96*7304104dSAndroid Build Coastguard Worker /* Prototype for option handler. */
97*7304104dSAndroid Build Coastguard Worker static error_t parse_opt (int key, char *arg, struct argp_state *state);
98*7304104dSAndroid Build Coastguard Worker
99*7304104dSAndroid Build Coastguard Worker static struct argp_child argp_children[2]; /* [0] is set in main. */
100*7304104dSAndroid Build Coastguard Worker
101*7304104dSAndroid Build Coastguard Worker /* Data structure to communicate with argp functions. */
102*7304104dSAndroid Build Coastguard Worker static const struct argp argp =
103*7304104dSAndroid Build Coastguard Worker {
104*7304104dSAndroid Build Coastguard Worker options, parse_opt, args_doc, doc, argp_children, NULL, NULL
105*7304104dSAndroid Build Coastguard Worker };
106*7304104dSAndroid Build Coastguard Worker
107*7304104dSAndroid Build Coastguard Worker
108*7304104dSAndroid Build Coastguard Worker /* Handle ADDR. */
109*7304104dSAndroid Build Coastguard Worker static int handle_address (const char *addr, Dwfl *dwfl);
110*7304104dSAndroid Build Coastguard Worker
111*7304104dSAndroid Build Coastguard Worker /* True when we should print the address for each entry. */
112*7304104dSAndroid Build Coastguard Worker static bool print_addresses;
113*7304104dSAndroid Build Coastguard Worker
114*7304104dSAndroid Build Coastguard Worker /* True if only base names of files should be shown. */
115*7304104dSAndroid Build Coastguard Worker static bool only_basenames;
116*7304104dSAndroid Build Coastguard Worker
117*7304104dSAndroid Build Coastguard Worker /* True if absolute file names based on DW_AT_comp_dir should be shown. */
118*7304104dSAndroid Build Coastguard Worker static bool use_comp_dir = true;
119*7304104dSAndroid Build Coastguard Worker
120*7304104dSAndroid Build Coastguard Worker /* True if line flags should be shown. */
121*7304104dSAndroid Build Coastguard Worker static bool show_flags;
122*7304104dSAndroid Build Coastguard Worker
123*7304104dSAndroid Build Coastguard Worker /* True if function names should be shown. */
124*7304104dSAndroid Build Coastguard Worker static bool show_functions;
125*7304104dSAndroid Build Coastguard Worker
126*7304104dSAndroid Build Coastguard Worker /* True if ELF symbol or section info should be shown. */
127*7304104dSAndroid Build Coastguard Worker static bool show_symbols;
128*7304104dSAndroid Build Coastguard Worker
129*7304104dSAndroid Build Coastguard Worker /* True if section associated with a symbol address should be shown. */
130*7304104dSAndroid Build Coastguard Worker static bool show_symbol_sections;
131*7304104dSAndroid Build Coastguard Worker
132*7304104dSAndroid Build Coastguard Worker /* If non-null, take address parameters as relative to named section. */
133*7304104dSAndroid Build Coastguard Worker static const char *just_section;
134*7304104dSAndroid Build Coastguard Worker
135*7304104dSAndroid Build Coastguard Worker /* True if all inlined subroutines of the current address should be shown. */
136*7304104dSAndroid Build Coastguard Worker static bool show_inlines;
137*7304104dSAndroid Build Coastguard Worker
138*7304104dSAndroid Build Coastguard Worker /* True if all names need to be demangled. */
139*7304104dSAndroid Build Coastguard Worker static bool demangle;
140*7304104dSAndroid Build Coastguard Worker
141*7304104dSAndroid Build Coastguard Worker /* True if all information should be printed on one line. */
142*7304104dSAndroid Build Coastguard Worker static bool pretty;
143*7304104dSAndroid Build Coastguard Worker
144*7304104dSAndroid Build Coastguard Worker #ifdef USE_DEMANGLE
145*7304104dSAndroid Build Coastguard Worker static size_t demangle_buffer_len = 0;
146*7304104dSAndroid Build Coastguard Worker static char *demangle_buffer = NULL;
147*7304104dSAndroid Build Coastguard Worker #endif
148*7304104dSAndroid Build Coastguard Worker
149*7304104dSAndroid Build Coastguard Worker int
main(int argc,char * argv[])150*7304104dSAndroid Build Coastguard Worker main (int argc, char *argv[])
151*7304104dSAndroid Build Coastguard Worker {
152*7304104dSAndroid Build Coastguard Worker int remaining;
153*7304104dSAndroid Build Coastguard Worker int result = 0;
154*7304104dSAndroid Build Coastguard Worker
155*7304104dSAndroid Build Coastguard Worker /* We use no threads here which can interfere with handling a stream. */
156*7304104dSAndroid Build Coastguard Worker (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
157*7304104dSAndroid Build Coastguard Worker
158*7304104dSAndroid Build Coastguard Worker /* Set locale. */
159*7304104dSAndroid Build Coastguard Worker (void) setlocale (LC_ALL, "");
160*7304104dSAndroid Build Coastguard Worker
161*7304104dSAndroid Build Coastguard Worker /* Make sure the message catalog can be found. */
162*7304104dSAndroid Build Coastguard Worker (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
163*7304104dSAndroid Build Coastguard Worker
164*7304104dSAndroid Build Coastguard Worker /* Initialize the message catalog. */
165*7304104dSAndroid Build Coastguard Worker (void) textdomain (PACKAGE_TARNAME);
166*7304104dSAndroid Build Coastguard Worker
167*7304104dSAndroid Build Coastguard Worker /* Parse and process arguments. This includes opening the modules. */
168*7304104dSAndroid Build Coastguard Worker argp_children[0].argp = dwfl_standard_argp ();
169*7304104dSAndroid Build Coastguard Worker argp_children[0].group = 1;
170*7304104dSAndroid Build Coastguard Worker Dwfl *dwfl = NULL;
171*7304104dSAndroid Build Coastguard Worker (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
172*7304104dSAndroid Build Coastguard Worker assert (dwfl != NULL);
173*7304104dSAndroid Build Coastguard Worker
174*7304104dSAndroid Build Coastguard Worker /* Now handle the addresses. In case none are given on the command
175*7304104dSAndroid Build Coastguard Worker line, read from stdin. */
176*7304104dSAndroid Build Coastguard Worker if (remaining == argc)
177*7304104dSAndroid Build Coastguard Worker {
178*7304104dSAndroid Build Coastguard Worker /* We use no threads here which can interfere with handling a stream. */
179*7304104dSAndroid Build Coastguard Worker (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
180*7304104dSAndroid Build Coastguard Worker
181*7304104dSAndroid Build Coastguard Worker char *buf = NULL;
182*7304104dSAndroid Build Coastguard Worker size_t len = 0;
183*7304104dSAndroid Build Coastguard Worker ssize_t chars;
184*7304104dSAndroid Build Coastguard Worker while (!feof_unlocked (stdin))
185*7304104dSAndroid Build Coastguard Worker {
186*7304104dSAndroid Build Coastguard Worker if ((chars = getline (&buf, &len, stdin)) < 0)
187*7304104dSAndroid Build Coastguard Worker break;
188*7304104dSAndroid Build Coastguard Worker
189*7304104dSAndroid Build Coastguard Worker if (buf[chars - 1] == '\n')
190*7304104dSAndroid Build Coastguard Worker buf[chars - 1] = '\0';
191*7304104dSAndroid Build Coastguard Worker
192*7304104dSAndroid Build Coastguard Worker result = handle_address (buf, dwfl);
193*7304104dSAndroid Build Coastguard Worker fflush (stdout);
194*7304104dSAndroid Build Coastguard Worker }
195*7304104dSAndroid Build Coastguard Worker
196*7304104dSAndroid Build Coastguard Worker free (buf);
197*7304104dSAndroid Build Coastguard Worker }
198*7304104dSAndroid Build Coastguard Worker else
199*7304104dSAndroid Build Coastguard Worker {
200*7304104dSAndroid Build Coastguard Worker do
201*7304104dSAndroid Build Coastguard Worker result = handle_address (argv[remaining], dwfl);
202*7304104dSAndroid Build Coastguard Worker while (++remaining < argc);
203*7304104dSAndroid Build Coastguard Worker }
204*7304104dSAndroid Build Coastguard Worker
205*7304104dSAndroid Build Coastguard Worker dwfl_end (dwfl);
206*7304104dSAndroid Build Coastguard Worker
207*7304104dSAndroid Build Coastguard Worker #ifdef USE_DEMANGLE
208*7304104dSAndroid Build Coastguard Worker free (demangle_buffer);
209*7304104dSAndroid Build Coastguard Worker #endif
210*7304104dSAndroid Build Coastguard Worker
211*7304104dSAndroid Build Coastguard Worker return result;
212*7304104dSAndroid Build Coastguard Worker }
213*7304104dSAndroid Build Coastguard Worker
214*7304104dSAndroid Build Coastguard Worker
215*7304104dSAndroid Build Coastguard Worker /* Handle program arguments. */
216*7304104dSAndroid Build Coastguard Worker static error_t
parse_opt(int key,char * arg,struct argp_state * state)217*7304104dSAndroid Build Coastguard Worker parse_opt (int key, char *arg, struct argp_state *state)
218*7304104dSAndroid Build Coastguard Worker {
219*7304104dSAndroid Build Coastguard Worker switch (key)
220*7304104dSAndroid Build Coastguard Worker {
221*7304104dSAndroid Build Coastguard Worker case ARGP_KEY_INIT:
222*7304104dSAndroid Build Coastguard Worker state->child_inputs[0] = state->input;
223*7304104dSAndroid Build Coastguard Worker break;
224*7304104dSAndroid Build Coastguard Worker
225*7304104dSAndroid Build Coastguard Worker case 'a':
226*7304104dSAndroid Build Coastguard Worker print_addresses = true;
227*7304104dSAndroid Build Coastguard Worker break;
228*7304104dSAndroid Build Coastguard Worker
229*7304104dSAndroid Build Coastguard Worker /* Ignore --target=bfdname. */
230*7304104dSAndroid Build Coastguard Worker case 'b':
231*7304104dSAndroid Build Coastguard Worker break;
232*7304104dSAndroid Build Coastguard Worker
233*7304104dSAndroid Build Coastguard Worker case 'C':
234*7304104dSAndroid Build Coastguard Worker case OPT_DEMANGLER:
235*7304104dSAndroid Build Coastguard Worker demangle = true;
236*7304104dSAndroid Build Coastguard Worker break;
237*7304104dSAndroid Build Coastguard Worker
238*7304104dSAndroid Build Coastguard Worker case 's':
239*7304104dSAndroid Build Coastguard Worker only_basenames = true;
240*7304104dSAndroid Build Coastguard Worker break;
241*7304104dSAndroid Build Coastguard Worker
242*7304104dSAndroid Build Coastguard Worker case 'A':
243*7304104dSAndroid Build Coastguard Worker use_comp_dir = true;
244*7304104dSAndroid Build Coastguard Worker break;
245*7304104dSAndroid Build Coastguard Worker
246*7304104dSAndroid Build Coastguard Worker case OPT_RELATIVE:
247*7304104dSAndroid Build Coastguard Worker use_comp_dir = false;
248*7304104dSAndroid Build Coastguard Worker break;
249*7304104dSAndroid Build Coastguard Worker
250*7304104dSAndroid Build Coastguard Worker case 'f':
251*7304104dSAndroid Build Coastguard Worker show_functions = true;
252*7304104dSAndroid Build Coastguard Worker break;
253*7304104dSAndroid Build Coastguard Worker
254*7304104dSAndroid Build Coastguard Worker case 'F':
255*7304104dSAndroid Build Coastguard Worker show_flags = true;
256*7304104dSAndroid Build Coastguard Worker break;
257*7304104dSAndroid Build Coastguard Worker
258*7304104dSAndroid Build Coastguard Worker case 'S':
259*7304104dSAndroid Build Coastguard Worker show_symbols = true;
260*7304104dSAndroid Build Coastguard Worker break;
261*7304104dSAndroid Build Coastguard Worker
262*7304104dSAndroid Build Coastguard Worker case 'x':
263*7304104dSAndroid Build Coastguard Worker show_symbols = true;
264*7304104dSAndroid Build Coastguard Worker show_symbol_sections = true;
265*7304104dSAndroid Build Coastguard Worker break;
266*7304104dSAndroid Build Coastguard Worker
267*7304104dSAndroid Build Coastguard Worker case 'j':
268*7304104dSAndroid Build Coastguard Worker just_section = arg;
269*7304104dSAndroid Build Coastguard Worker break;
270*7304104dSAndroid Build Coastguard Worker
271*7304104dSAndroid Build Coastguard Worker case 'i':
272*7304104dSAndroid Build Coastguard Worker show_inlines = true;
273*7304104dSAndroid Build Coastguard Worker break;
274*7304104dSAndroid Build Coastguard Worker
275*7304104dSAndroid Build Coastguard Worker case OPT_PRETTY:
276*7304104dSAndroid Build Coastguard Worker pretty = true;
277*7304104dSAndroid Build Coastguard Worker break;
278*7304104dSAndroid Build Coastguard Worker
279*7304104dSAndroid Build Coastguard Worker default:
280*7304104dSAndroid Build Coastguard Worker return ARGP_ERR_UNKNOWN;
281*7304104dSAndroid Build Coastguard Worker }
282*7304104dSAndroid Build Coastguard Worker return 0;
283*7304104dSAndroid Build Coastguard Worker }
284*7304104dSAndroid Build Coastguard Worker
285*7304104dSAndroid Build Coastguard Worker static const char *
symname(const char * name)286*7304104dSAndroid Build Coastguard Worker symname (const char *name)
287*7304104dSAndroid Build Coastguard Worker {
288*7304104dSAndroid Build Coastguard Worker #ifdef USE_DEMANGLE
289*7304104dSAndroid Build Coastguard Worker // Require GNU v3 ABI by the "_Z" prefix.
290*7304104dSAndroid Build Coastguard Worker if (demangle && name[0] == '_' && name[1] == 'Z')
291*7304104dSAndroid Build Coastguard Worker {
292*7304104dSAndroid Build Coastguard Worker int status = -1;
293*7304104dSAndroid Build Coastguard Worker char *dsymname = __cxa_demangle (name, demangle_buffer,
294*7304104dSAndroid Build Coastguard Worker &demangle_buffer_len, &status);
295*7304104dSAndroid Build Coastguard Worker if (status == 0)
296*7304104dSAndroid Build Coastguard Worker name = demangle_buffer = dsymname;
297*7304104dSAndroid Build Coastguard Worker }
298*7304104dSAndroid Build Coastguard Worker #endif
299*7304104dSAndroid Build Coastguard Worker return name;
300*7304104dSAndroid Build Coastguard Worker }
301*7304104dSAndroid Build Coastguard Worker
302*7304104dSAndroid Build Coastguard Worker static const char *
get_diename(Dwarf_Die * die)303*7304104dSAndroid Build Coastguard Worker get_diename (Dwarf_Die *die)
304*7304104dSAndroid Build Coastguard Worker {
305*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr;
306*7304104dSAndroid Build Coastguard Worker const char *name;
307*7304104dSAndroid Build Coastguard Worker
308*7304104dSAndroid Build Coastguard Worker name = dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name,
309*7304104dSAndroid Build Coastguard Worker &attr)
310*7304104dSAndroid Build Coastguard Worker ?: dwarf_attr_integrate (die, DW_AT_linkage_name,
311*7304104dSAndroid Build Coastguard Worker &attr));
312*7304104dSAndroid Build Coastguard Worker
313*7304104dSAndroid Build Coastguard Worker if (name == NULL)
314*7304104dSAndroid Build Coastguard Worker name = dwarf_diename (die) ?: "??";
315*7304104dSAndroid Build Coastguard Worker
316*7304104dSAndroid Build Coastguard Worker return name;
317*7304104dSAndroid Build Coastguard Worker }
318*7304104dSAndroid Build Coastguard Worker
319*7304104dSAndroid Build Coastguard Worker static bool
print_dwarf_function(Dwfl_Module * mod,Dwarf_Addr addr)320*7304104dSAndroid Build Coastguard Worker print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
321*7304104dSAndroid Build Coastguard Worker {
322*7304104dSAndroid Build Coastguard Worker Dwarf_Addr bias = 0;
323*7304104dSAndroid Build Coastguard Worker Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
324*7304104dSAndroid Build Coastguard Worker
325*7304104dSAndroid Build Coastguard Worker Dwarf_Die *scopes;
326*7304104dSAndroid Build Coastguard Worker int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
327*7304104dSAndroid Build Coastguard Worker if (nscopes <= 0)
328*7304104dSAndroid Build Coastguard Worker return false;
329*7304104dSAndroid Build Coastguard Worker
330*7304104dSAndroid Build Coastguard Worker bool res = false;
331*7304104dSAndroid Build Coastguard Worker for (int i = 0; i < nscopes; ++i)
332*7304104dSAndroid Build Coastguard Worker switch (dwarf_tag (&scopes[i]))
333*7304104dSAndroid Build Coastguard Worker {
334*7304104dSAndroid Build Coastguard Worker case DW_TAG_subprogram:
335*7304104dSAndroid Build Coastguard Worker {
336*7304104dSAndroid Build Coastguard Worker const char *name = get_diename (&scopes[i]);
337*7304104dSAndroid Build Coastguard Worker if (name == NULL)
338*7304104dSAndroid Build Coastguard Worker goto done;
339*7304104dSAndroid Build Coastguard Worker printf ("%s%c", symname (name), pretty ? ' ' : '\n');
340*7304104dSAndroid Build Coastguard Worker res = true;
341*7304104dSAndroid Build Coastguard Worker goto done;
342*7304104dSAndroid Build Coastguard Worker }
343*7304104dSAndroid Build Coastguard Worker
344*7304104dSAndroid Build Coastguard Worker case DW_TAG_inlined_subroutine:
345*7304104dSAndroid Build Coastguard Worker {
346*7304104dSAndroid Build Coastguard Worker const char *name = get_diename (&scopes[i]);
347*7304104dSAndroid Build Coastguard Worker if (name == NULL)
348*7304104dSAndroid Build Coastguard Worker goto done;
349*7304104dSAndroid Build Coastguard Worker
350*7304104dSAndroid Build Coastguard Worker /* When using --pretty-print we only show inlines on their
351*7304104dSAndroid Build Coastguard Worker own line. Just print the first subroutine name. */
352*7304104dSAndroid Build Coastguard Worker if (pretty)
353*7304104dSAndroid Build Coastguard Worker {
354*7304104dSAndroid Build Coastguard Worker printf ("%s ", symname (name));
355*7304104dSAndroid Build Coastguard Worker res = true;
356*7304104dSAndroid Build Coastguard Worker goto done;
357*7304104dSAndroid Build Coastguard Worker }
358*7304104dSAndroid Build Coastguard Worker else
359*7304104dSAndroid Build Coastguard Worker printf ("%s inlined", symname (name));
360*7304104dSAndroid Build Coastguard Worker
361*7304104dSAndroid Build Coastguard Worker Dwarf_Files *files;
362*7304104dSAndroid Build Coastguard Worker if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
363*7304104dSAndroid Build Coastguard Worker {
364*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr_mem;
365*7304104dSAndroid Build Coastguard Worker Dwarf_Word val;
366*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr (&scopes[i],
367*7304104dSAndroid Build Coastguard Worker DW_AT_call_file,
368*7304104dSAndroid Build Coastguard Worker &attr_mem), &val) == 0)
369*7304104dSAndroid Build Coastguard Worker {
370*7304104dSAndroid Build Coastguard Worker const char *file = dwarf_filesrc (files, val, NULL, NULL);
371*7304104dSAndroid Build Coastguard Worker unsigned int lineno = 0;
372*7304104dSAndroid Build Coastguard Worker unsigned int colno = 0;
373*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr (&scopes[i],
374*7304104dSAndroid Build Coastguard Worker DW_AT_call_line,
375*7304104dSAndroid Build Coastguard Worker &attr_mem), &val) == 0)
376*7304104dSAndroid Build Coastguard Worker lineno = val;
377*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr (&scopes[i],
378*7304104dSAndroid Build Coastguard Worker DW_AT_call_column,
379*7304104dSAndroid Build Coastguard Worker &attr_mem), &val) == 0)
380*7304104dSAndroid Build Coastguard Worker colno = val;
381*7304104dSAndroid Build Coastguard Worker
382*7304104dSAndroid Build Coastguard Worker const char *comp_dir = "";
383*7304104dSAndroid Build Coastguard Worker const char *comp_dir_sep = "";
384*7304104dSAndroid Build Coastguard Worker
385*7304104dSAndroid Build Coastguard Worker if (file == NULL)
386*7304104dSAndroid Build Coastguard Worker file = "???";
387*7304104dSAndroid Build Coastguard Worker else if (only_basenames)
388*7304104dSAndroid Build Coastguard Worker file = xbasename (file);
389*7304104dSAndroid Build Coastguard Worker else if (use_comp_dir && file[0] != '/')
390*7304104dSAndroid Build Coastguard Worker {
391*7304104dSAndroid Build Coastguard Worker const char *const *dirs;
392*7304104dSAndroid Build Coastguard Worker size_t ndirs;
393*7304104dSAndroid Build Coastguard Worker if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0
394*7304104dSAndroid Build Coastguard Worker && dirs[0] != NULL)
395*7304104dSAndroid Build Coastguard Worker {
396*7304104dSAndroid Build Coastguard Worker comp_dir = dirs[0];
397*7304104dSAndroid Build Coastguard Worker comp_dir_sep = "/";
398*7304104dSAndroid Build Coastguard Worker }
399*7304104dSAndroid Build Coastguard Worker }
400*7304104dSAndroid Build Coastguard Worker
401*7304104dSAndroid Build Coastguard Worker if (lineno == 0)
402*7304104dSAndroid Build Coastguard Worker printf (" from %s%s%s",
403*7304104dSAndroid Build Coastguard Worker comp_dir, comp_dir_sep, file);
404*7304104dSAndroid Build Coastguard Worker else if (colno == 0)
405*7304104dSAndroid Build Coastguard Worker printf (" at %s%s%s:%u",
406*7304104dSAndroid Build Coastguard Worker comp_dir, comp_dir_sep, file, lineno);
407*7304104dSAndroid Build Coastguard Worker else
408*7304104dSAndroid Build Coastguard Worker printf (" at %s%s%s:%u:%u",
409*7304104dSAndroid Build Coastguard Worker comp_dir, comp_dir_sep, file, lineno, colno);
410*7304104dSAndroid Build Coastguard Worker }
411*7304104dSAndroid Build Coastguard Worker }
412*7304104dSAndroid Build Coastguard Worker printf (" in ");
413*7304104dSAndroid Build Coastguard Worker continue;
414*7304104dSAndroid Build Coastguard Worker }
415*7304104dSAndroid Build Coastguard Worker }
416*7304104dSAndroid Build Coastguard Worker
417*7304104dSAndroid Build Coastguard Worker done:
418*7304104dSAndroid Build Coastguard Worker free (scopes);
419*7304104dSAndroid Build Coastguard Worker return res;
420*7304104dSAndroid Build Coastguard Worker }
421*7304104dSAndroid Build Coastguard Worker
422*7304104dSAndroid Build Coastguard Worker static void
print_addrsym(Dwfl_Module * mod,GElf_Addr addr)423*7304104dSAndroid Build Coastguard Worker print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
424*7304104dSAndroid Build Coastguard Worker {
425*7304104dSAndroid Build Coastguard Worker GElf_Sym s;
426*7304104dSAndroid Build Coastguard Worker GElf_Off off;
427*7304104dSAndroid Build Coastguard Worker const char *name = dwfl_module_addrinfo (mod, addr, &off, &s,
428*7304104dSAndroid Build Coastguard Worker NULL, NULL, NULL);
429*7304104dSAndroid Build Coastguard Worker if (name == NULL)
430*7304104dSAndroid Build Coastguard Worker {
431*7304104dSAndroid Build Coastguard Worker /* No symbol name. Get a section name instead. */
432*7304104dSAndroid Build Coastguard Worker int i = dwfl_module_relocate_address (mod, &addr);
433*7304104dSAndroid Build Coastguard Worker if (i >= 0)
434*7304104dSAndroid Build Coastguard Worker name = dwfl_module_relocation_info (mod, i, NULL);
435*7304104dSAndroid Build Coastguard Worker if (name == NULL)
436*7304104dSAndroid Build Coastguard Worker printf ("??%c", pretty ? ' ': '\n');
437*7304104dSAndroid Build Coastguard Worker else
438*7304104dSAndroid Build Coastguard Worker printf ("(%s)+%#" PRIx64 "%c", name, addr, pretty ? ' ' : '\n');
439*7304104dSAndroid Build Coastguard Worker }
440*7304104dSAndroid Build Coastguard Worker else
441*7304104dSAndroid Build Coastguard Worker {
442*7304104dSAndroid Build Coastguard Worker name = symname (name);
443*7304104dSAndroid Build Coastguard Worker if (off == 0)
444*7304104dSAndroid Build Coastguard Worker printf ("%s", name);
445*7304104dSAndroid Build Coastguard Worker else
446*7304104dSAndroid Build Coastguard Worker printf ("%s+%#" PRIx64 "", name, off);
447*7304104dSAndroid Build Coastguard Worker
448*7304104dSAndroid Build Coastguard Worker // Also show section name for address.
449*7304104dSAndroid Build Coastguard Worker if (show_symbol_sections)
450*7304104dSAndroid Build Coastguard Worker {
451*7304104dSAndroid Build Coastguard Worker Dwarf_Addr ebias;
452*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
453*7304104dSAndroid Build Coastguard Worker if (scn != NULL)
454*7304104dSAndroid Build Coastguard Worker {
455*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
456*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
457*7304104dSAndroid Build Coastguard Worker if (shdr != NULL)
458*7304104dSAndroid Build Coastguard Worker {
459*7304104dSAndroid Build Coastguard Worker Elf *elf = dwfl_module_getelf (mod, &ebias);
460*7304104dSAndroid Build Coastguard Worker size_t shstrndx;
461*7304104dSAndroid Build Coastguard Worker if (elf_getshdrstrndx (elf, &shstrndx) >= 0)
462*7304104dSAndroid Build Coastguard Worker printf (" (%s)", elf_strptr (elf, shstrndx,
463*7304104dSAndroid Build Coastguard Worker shdr->sh_name));
464*7304104dSAndroid Build Coastguard Worker }
465*7304104dSAndroid Build Coastguard Worker }
466*7304104dSAndroid Build Coastguard Worker }
467*7304104dSAndroid Build Coastguard Worker printf ("%c", pretty ? ' ' : '\n');
468*7304104dSAndroid Build Coastguard Worker }
469*7304104dSAndroid Build Coastguard Worker }
470*7304104dSAndroid Build Coastguard Worker
471*7304104dSAndroid Build Coastguard Worker static int
see_one_module(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr start,void * arg)472*7304104dSAndroid Build Coastguard Worker see_one_module (Dwfl_Module *mod,
473*7304104dSAndroid Build Coastguard Worker void **userdata __attribute__ ((unused)),
474*7304104dSAndroid Build Coastguard Worker const char *name __attribute__ ((unused)),
475*7304104dSAndroid Build Coastguard Worker Dwarf_Addr start __attribute__ ((unused)),
476*7304104dSAndroid Build Coastguard Worker void *arg)
477*7304104dSAndroid Build Coastguard Worker {
478*7304104dSAndroid Build Coastguard Worker Dwfl_Module **result = arg;
479*7304104dSAndroid Build Coastguard Worker if (*result != NULL)
480*7304104dSAndroid Build Coastguard Worker return DWARF_CB_ABORT;
481*7304104dSAndroid Build Coastguard Worker *result = mod;
482*7304104dSAndroid Build Coastguard Worker return DWARF_CB_OK;
483*7304104dSAndroid Build Coastguard Worker }
484*7304104dSAndroid Build Coastguard Worker
485*7304104dSAndroid Build Coastguard Worker static int
find_symbol(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr start,void * arg)486*7304104dSAndroid Build Coastguard Worker find_symbol (Dwfl_Module *mod,
487*7304104dSAndroid Build Coastguard Worker void **userdata __attribute__ ((unused)),
488*7304104dSAndroid Build Coastguard Worker const char *name __attribute__ ((unused)),
489*7304104dSAndroid Build Coastguard Worker Dwarf_Addr start __attribute__ ((unused)),
490*7304104dSAndroid Build Coastguard Worker void *arg)
491*7304104dSAndroid Build Coastguard Worker {
492*7304104dSAndroid Build Coastguard Worker const char *looking_for = ((void **) arg)[0];
493*7304104dSAndroid Build Coastguard Worker GElf_Sym *symbol = ((void **) arg)[1];
494*7304104dSAndroid Build Coastguard Worker GElf_Addr *value = ((void **) arg)[2];
495*7304104dSAndroid Build Coastguard Worker
496*7304104dSAndroid Build Coastguard Worker int n = dwfl_module_getsymtab (mod);
497*7304104dSAndroid Build Coastguard Worker for (int i = 1; i < n; ++i)
498*7304104dSAndroid Build Coastguard Worker {
499*7304104dSAndroid Build Coastguard Worker const char *symbol_name = dwfl_module_getsym_info (mod, i, symbol,
500*7304104dSAndroid Build Coastguard Worker value, NULL, NULL,
501*7304104dSAndroid Build Coastguard Worker NULL);
502*7304104dSAndroid Build Coastguard Worker if (symbol_name == NULL || symbol_name[0] == '\0')
503*7304104dSAndroid Build Coastguard Worker continue;
504*7304104dSAndroid Build Coastguard Worker switch (GELF_ST_TYPE (symbol->st_info))
505*7304104dSAndroid Build Coastguard Worker {
506*7304104dSAndroid Build Coastguard Worker case STT_SECTION:
507*7304104dSAndroid Build Coastguard Worker case STT_FILE:
508*7304104dSAndroid Build Coastguard Worker case STT_TLS:
509*7304104dSAndroid Build Coastguard Worker break;
510*7304104dSAndroid Build Coastguard Worker default:
511*7304104dSAndroid Build Coastguard Worker if (!strcmp (symbol_name, looking_for))
512*7304104dSAndroid Build Coastguard Worker {
513*7304104dSAndroid Build Coastguard Worker ((void **) arg)[0] = NULL;
514*7304104dSAndroid Build Coastguard Worker return DWARF_CB_ABORT;
515*7304104dSAndroid Build Coastguard Worker }
516*7304104dSAndroid Build Coastguard Worker }
517*7304104dSAndroid Build Coastguard Worker }
518*7304104dSAndroid Build Coastguard Worker
519*7304104dSAndroid Build Coastguard Worker return DWARF_CB_OK;
520*7304104dSAndroid Build Coastguard Worker }
521*7304104dSAndroid Build Coastguard Worker
522*7304104dSAndroid Build Coastguard Worker static bool
adjust_to_section(const char * name,uintmax_t * addr,Dwfl * dwfl)523*7304104dSAndroid Build Coastguard Worker adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
524*7304104dSAndroid Build Coastguard Worker {
525*7304104dSAndroid Build Coastguard Worker /* It was (section)+offset. This makes sense if there is
526*7304104dSAndroid Build Coastguard Worker only one module to look in for a section. */
527*7304104dSAndroid Build Coastguard Worker Dwfl_Module *mod = NULL;
528*7304104dSAndroid Build Coastguard Worker if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0
529*7304104dSAndroid Build Coastguard Worker || mod == NULL)
530*7304104dSAndroid Build Coastguard Worker error_exit (0, _("Section syntax requires exactly one module"));
531*7304104dSAndroid Build Coastguard Worker
532*7304104dSAndroid Build Coastguard Worker int nscn = dwfl_module_relocations (mod);
533*7304104dSAndroid Build Coastguard Worker for (int i = 0; i < nscn; ++i)
534*7304104dSAndroid Build Coastguard Worker {
535*7304104dSAndroid Build Coastguard Worker GElf_Word shndx;
536*7304104dSAndroid Build Coastguard Worker const char *scn = dwfl_module_relocation_info (mod, i, &shndx);
537*7304104dSAndroid Build Coastguard Worker if (unlikely (scn == NULL))
538*7304104dSAndroid Build Coastguard Worker break;
539*7304104dSAndroid Build Coastguard Worker if (!strcmp (scn, name))
540*7304104dSAndroid Build Coastguard Worker {
541*7304104dSAndroid Build Coastguard Worker /* Found the section. */
542*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
543*7304104dSAndroid Build Coastguard Worker GElf_Addr shdr_bias;
544*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr
545*7304104dSAndroid Build Coastguard Worker (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx),
546*7304104dSAndroid Build Coastguard Worker &shdr_mem);
547*7304104dSAndroid Build Coastguard Worker if (unlikely (shdr == NULL))
548*7304104dSAndroid Build Coastguard Worker break;
549*7304104dSAndroid Build Coastguard Worker
550*7304104dSAndroid Build Coastguard Worker if (*addr >= shdr->sh_size)
551*7304104dSAndroid Build Coastguard Worker error (0, 0,
552*7304104dSAndroid Build Coastguard Worker _("offset %#" PRIxMAX " lies outside"
553*7304104dSAndroid Build Coastguard Worker " section '%s'"),
554*7304104dSAndroid Build Coastguard Worker *addr, scn);
555*7304104dSAndroid Build Coastguard Worker
556*7304104dSAndroid Build Coastguard Worker *addr += shdr->sh_addr + shdr_bias;
557*7304104dSAndroid Build Coastguard Worker return true;
558*7304104dSAndroid Build Coastguard Worker }
559*7304104dSAndroid Build Coastguard Worker }
560*7304104dSAndroid Build Coastguard Worker
561*7304104dSAndroid Build Coastguard Worker return false;
562*7304104dSAndroid Build Coastguard Worker }
563*7304104dSAndroid Build Coastguard Worker
564*7304104dSAndroid Build Coastguard Worker static void
print_src(const char * src,int lineno,int linecol,Dwarf_Die * cu)565*7304104dSAndroid Build Coastguard Worker print_src (const char *src, int lineno, int linecol, Dwarf_Die *cu)
566*7304104dSAndroid Build Coastguard Worker {
567*7304104dSAndroid Build Coastguard Worker const char *comp_dir = "";
568*7304104dSAndroid Build Coastguard Worker const char *comp_dir_sep = "";
569*7304104dSAndroid Build Coastguard Worker
570*7304104dSAndroid Build Coastguard Worker if (only_basenames)
571*7304104dSAndroid Build Coastguard Worker src = xbasename (src);
572*7304104dSAndroid Build Coastguard Worker else if (use_comp_dir && src[0] != '/')
573*7304104dSAndroid Build Coastguard Worker {
574*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr;
575*7304104dSAndroid Build Coastguard Worker comp_dir = dwarf_formstring (dwarf_attr (cu, DW_AT_comp_dir, &attr));
576*7304104dSAndroid Build Coastguard Worker if (comp_dir != NULL)
577*7304104dSAndroid Build Coastguard Worker comp_dir_sep = "/";
578*7304104dSAndroid Build Coastguard Worker }
579*7304104dSAndroid Build Coastguard Worker
580*7304104dSAndroid Build Coastguard Worker if (linecol != 0)
581*7304104dSAndroid Build Coastguard Worker printf ("%s%s%s:%d:%d",
582*7304104dSAndroid Build Coastguard Worker comp_dir, comp_dir_sep, src, lineno, linecol);
583*7304104dSAndroid Build Coastguard Worker else
584*7304104dSAndroid Build Coastguard Worker printf ("%s%s%s:%d",
585*7304104dSAndroid Build Coastguard Worker comp_dir, comp_dir_sep, src, lineno);
586*7304104dSAndroid Build Coastguard Worker }
587*7304104dSAndroid Build Coastguard Worker
588*7304104dSAndroid Build Coastguard Worker static int
get_addr_width(Dwfl_Module * mod)589*7304104dSAndroid Build Coastguard Worker get_addr_width (Dwfl_Module *mod)
590*7304104dSAndroid Build Coastguard Worker {
591*7304104dSAndroid Build Coastguard Worker // Try to find the address width if possible.
592*7304104dSAndroid Build Coastguard Worker static int width = 0;
593*7304104dSAndroid Build Coastguard Worker if (width == 0 && mod != NULL)
594*7304104dSAndroid Build Coastguard Worker {
595*7304104dSAndroid Build Coastguard Worker Dwarf_Addr bias;
596*7304104dSAndroid Build Coastguard Worker Elf *elf = dwfl_module_getelf (mod, &bias);
597*7304104dSAndroid Build Coastguard Worker if (elf != NULL)
598*7304104dSAndroid Build Coastguard Worker {
599*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr_mem;
600*7304104dSAndroid Build Coastguard Worker GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
601*7304104dSAndroid Build Coastguard Worker if (ehdr != NULL)
602*7304104dSAndroid Build Coastguard Worker width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16;
603*7304104dSAndroid Build Coastguard Worker }
604*7304104dSAndroid Build Coastguard Worker }
605*7304104dSAndroid Build Coastguard Worker if (width == 0)
606*7304104dSAndroid Build Coastguard Worker width = 16;
607*7304104dSAndroid Build Coastguard Worker
608*7304104dSAndroid Build Coastguard Worker return width;
609*7304104dSAndroid Build Coastguard Worker }
610*7304104dSAndroid Build Coastguard Worker
611*7304104dSAndroid Build Coastguard Worker static inline void
show_note(int (* get)(Dwarf_Line *,bool *),Dwarf_Line * info,const char * note)612*7304104dSAndroid Build Coastguard Worker show_note (int (*get) (Dwarf_Line *, bool *),
613*7304104dSAndroid Build Coastguard Worker Dwarf_Line *info,
614*7304104dSAndroid Build Coastguard Worker const char *note)
615*7304104dSAndroid Build Coastguard Worker {
616*7304104dSAndroid Build Coastguard Worker bool flag;
617*7304104dSAndroid Build Coastguard Worker if ((*get) (info, &flag) == 0 && flag)
618*7304104dSAndroid Build Coastguard Worker fputs (note, stdout);
619*7304104dSAndroid Build Coastguard Worker }
620*7304104dSAndroid Build Coastguard Worker
621*7304104dSAndroid Build Coastguard Worker static inline void
show_int(int (* get)(Dwarf_Line *,unsigned int *),Dwarf_Line * info,const char * name)622*7304104dSAndroid Build Coastguard Worker show_int (int (*get) (Dwarf_Line *, unsigned int *),
623*7304104dSAndroid Build Coastguard Worker Dwarf_Line *info,
624*7304104dSAndroid Build Coastguard Worker const char *name)
625*7304104dSAndroid Build Coastguard Worker {
626*7304104dSAndroid Build Coastguard Worker unsigned int val;
627*7304104dSAndroid Build Coastguard Worker if ((*get) (info, &val) == 0 && val != 0)
628*7304104dSAndroid Build Coastguard Worker printf (" (%s %u)", name, val);
629*7304104dSAndroid Build Coastguard Worker }
630*7304104dSAndroid Build Coastguard Worker
631*7304104dSAndroid Build Coastguard Worker static int
handle_address(const char * string,Dwfl * dwfl)632*7304104dSAndroid Build Coastguard Worker handle_address (const char *string, Dwfl *dwfl)
633*7304104dSAndroid Build Coastguard Worker {
634*7304104dSAndroid Build Coastguard Worker char *endp;
635*7304104dSAndroid Build Coastguard Worker uintmax_t addr = strtoumax (string, &endp, 16);
636*7304104dSAndroid Build Coastguard Worker if (endp == string || *endp != '\0')
637*7304104dSAndroid Build Coastguard Worker {
638*7304104dSAndroid Build Coastguard Worker bool parsed = false;
639*7304104dSAndroid Build Coastguard Worker int i, j;
640*7304104dSAndroid Build Coastguard Worker char *name = NULL;
641*7304104dSAndroid Build Coastguard Worker if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2
642*7304104dSAndroid Build Coastguard Worker && string[i] == '\0')
643*7304104dSAndroid Build Coastguard Worker parsed = adjust_to_section (name, &addr, dwfl);
644*7304104dSAndroid Build Coastguard Worker switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j))
645*7304104dSAndroid Build Coastguard Worker {
646*7304104dSAndroid Build Coastguard Worker default:
647*7304104dSAndroid Build Coastguard Worker break;
648*7304104dSAndroid Build Coastguard Worker case 1:
649*7304104dSAndroid Build Coastguard Worker addr = 0;
650*7304104dSAndroid Build Coastguard Worker j = i;
651*7304104dSAndroid Build Coastguard Worker FALLTHROUGH;
652*7304104dSAndroid Build Coastguard Worker case 2:
653*7304104dSAndroid Build Coastguard Worker if (string[j] != '\0')
654*7304104dSAndroid Build Coastguard Worker break;
655*7304104dSAndroid Build Coastguard Worker
656*7304104dSAndroid Build Coastguard Worker /* It was symbol[+offset]. */
657*7304104dSAndroid Build Coastguard Worker GElf_Sym sym;
658*7304104dSAndroid Build Coastguard Worker GElf_Addr value = 0;
659*7304104dSAndroid Build Coastguard Worker void *arg[3] = { name, &sym, &value };
660*7304104dSAndroid Build Coastguard Worker (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
661*7304104dSAndroid Build Coastguard Worker if (arg[0] != NULL)
662*7304104dSAndroid Build Coastguard Worker error (0, 0, _("cannot find symbol '%s'"), name);
663*7304104dSAndroid Build Coastguard Worker else
664*7304104dSAndroid Build Coastguard Worker {
665*7304104dSAndroid Build Coastguard Worker if (sym.st_size != 0 && addr >= sym.st_size)
666*7304104dSAndroid Build Coastguard Worker error (0, 0,
667*7304104dSAndroid Build Coastguard Worker _("offset %#" PRIxMAX " lies outside"
668*7304104dSAndroid Build Coastguard Worker " contents of '%s'"),
669*7304104dSAndroid Build Coastguard Worker addr, name);
670*7304104dSAndroid Build Coastguard Worker addr += value;
671*7304104dSAndroid Build Coastguard Worker parsed = true;
672*7304104dSAndroid Build Coastguard Worker }
673*7304104dSAndroid Build Coastguard Worker break;
674*7304104dSAndroid Build Coastguard Worker }
675*7304104dSAndroid Build Coastguard Worker
676*7304104dSAndroid Build Coastguard Worker free (name);
677*7304104dSAndroid Build Coastguard Worker if (!parsed)
678*7304104dSAndroid Build Coastguard Worker return 1;
679*7304104dSAndroid Build Coastguard Worker }
680*7304104dSAndroid Build Coastguard Worker else if (just_section != NULL
681*7304104dSAndroid Build Coastguard Worker && !adjust_to_section (just_section, &addr, dwfl))
682*7304104dSAndroid Build Coastguard Worker return 1;
683*7304104dSAndroid Build Coastguard Worker
684*7304104dSAndroid Build Coastguard Worker Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
685*7304104dSAndroid Build Coastguard Worker
686*7304104dSAndroid Build Coastguard Worker if (print_addresses)
687*7304104dSAndroid Build Coastguard Worker {
688*7304104dSAndroid Build Coastguard Worker int width = get_addr_width (mod);
689*7304104dSAndroid Build Coastguard Worker printf ("0x%.*" PRIx64 "%s", width, addr, pretty ? ": " : "\n");
690*7304104dSAndroid Build Coastguard Worker }
691*7304104dSAndroid Build Coastguard Worker
692*7304104dSAndroid Build Coastguard Worker if (show_functions)
693*7304104dSAndroid Build Coastguard Worker {
694*7304104dSAndroid Build Coastguard Worker /* First determine the function name. Use the DWARF information if
695*7304104dSAndroid Build Coastguard Worker possible. */
696*7304104dSAndroid Build Coastguard Worker if (! print_dwarf_function (mod, addr) && !show_symbols)
697*7304104dSAndroid Build Coastguard Worker {
698*7304104dSAndroid Build Coastguard Worker const char *name = dwfl_module_addrname (mod, addr);
699*7304104dSAndroid Build Coastguard Worker name = name != NULL ? symname (name) : "??";
700*7304104dSAndroid Build Coastguard Worker printf ("%s%c", name, pretty ? ' ' : '\n');
701*7304104dSAndroid Build Coastguard Worker }
702*7304104dSAndroid Build Coastguard Worker }
703*7304104dSAndroid Build Coastguard Worker
704*7304104dSAndroid Build Coastguard Worker if (show_symbols)
705*7304104dSAndroid Build Coastguard Worker print_addrsym (mod, addr);
706*7304104dSAndroid Build Coastguard Worker
707*7304104dSAndroid Build Coastguard Worker if ((show_functions || show_symbols) && pretty)
708*7304104dSAndroid Build Coastguard Worker printf ("at ");
709*7304104dSAndroid Build Coastguard Worker
710*7304104dSAndroid Build Coastguard Worker Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
711*7304104dSAndroid Build Coastguard Worker
712*7304104dSAndroid Build Coastguard Worker const char *src;
713*7304104dSAndroid Build Coastguard Worker int lineno, linecol;
714*7304104dSAndroid Build Coastguard Worker
715*7304104dSAndroid Build Coastguard Worker if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
716*7304104dSAndroid Build Coastguard Worker NULL, NULL)) != NULL)
717*7304104dSAndroid Build Coastguard Worker {
718*7304104dSAndroid Build Coastguard Worker print_src (src, lineno, linecol, dwfl_linecu (line));
719*7304104dSAndroid Build Coastguard Worker if (show_flags)
720*7304104dSAndroid Build Coastguard Worker {
721*7304104dSAndroid Build Coastguard Worker Dwarf_Addr bias;
722*7304104dSAndroid Build Coastguard Worker Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
723*7304104dSAndroid Build Coastguard Worker assert (info != NULL);
724*7304104dSAndroid Build Coastguard Worker
725*7304104dSAndroid Build Coastguard Worker show_note (&dwarf_linebeginstatement, info, " (is_stmt)");
726*7304104dSAndroid Build Coastguard Worker show_note (&dwarf_lineblock, info, " (basic_block)");
727*7304104dSAndroid Build Coastguard Worker show_note (&dwarf_lineprologueend, info, " (prologue_end)");
728*7304104dSAndroid Build Coastguard Worker show_note (&dwarf_lineepiloguebegin, info, " (epilogue_begin)");
729*7304104dSAndroid Build Coastguard Worker show_int (&dwarf_lineisa, info, "isa");
730*7304104dSAndroid Build Coastguard Worker show_int (&dwarf_linediscriminator, info, "discriminator");
731*7304104dSAndroid Build Coastguard Worker }
732*7304104dSAndroid Build Coastguard Worker putchar ('\n');
733*7304104dSAndroid Build Coastguard Worker }
734*7304104dSAndroid Build Coastguard Worker else
735*7304104dSAndroid Build Coastguard Worker puts ("??:0");
736*7304104dSAndroid Build Coastguard Worker
737*7304104dSAndroid Build Coastguard Worker if (show_inlines)
738*7304104dSAndroid Build Coastguard Worker {
739*7304104dSAndroid Build Coastguard Worker Dwarf_Addr bias = 0;
740*7304104dSAndroid Build Coastguard Worker Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
741*7304104dSAndroid Build Coastguard Worker
742*7304104dSAndroid Build Coastguard Worker Dwarf_Die *scopes = NULL;
743*7304104dSAndroid Build Coastguard Worker int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
744*7304104dSAndroid Build Coastguard Worker if (nscopes < 0)
745*7304104dSAndroid Build Coastguard Worker return 1;
746*7304104dSAndroid Build Coastguard Worker
747*7304104dSAndroid Build Coastguard Worker if (nscopes > 0)
748*7304104dSAndroid Build Coastguard Worker {
749*7304104dSAndroid Build Coastguard Worker Dwarf_Die subroutine;
750*7304104dSAndroid Build Coastguard Worker Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]);
751*7304104dSAndroid Build Coastguard Worker dwarf_offdie (dwfl_module_getdwarf (mod, &bias),
752*7304104dSAndroid Build Coastguard Worker dieoff, &subroutine);
753*7304104dSAndroid Build Coastguard Worker free (scopes);
754*7304104dSAndroid Build Coastguard Worker scopes = NULL;
755*7304104dSAndroid Build Coastguard Worker
756*7304104dSAndroid Build Coastguard Worker nscopes = dwarf_getscopes_die (&subroutine, &scopes);
757*7304104dSAndroid Build Coastguard Worker if (nscopes > 1)
758*7304104dSAndroid Build Coastguard Worker {
759*7304104dSAndroid Build Coastguard Worker Dwarf_Die cu;
760*7304104dSAndroid Build Coastguard Worker Dwarf_Files *files;
761*7304104dSAndroid Build Coastguard Worker if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL
762*7304104dSAndroid Build Coastguard Worker && dwarf_getsrcfiles (cudie, &files, NULL) == 0)
763*7304104dSAndroid Build Coastguard Worker {
764*7304104dSAndroid Build Coastguard Worker for (int i = 0; i < nscopes - 1; i++)
765*7304104dSAndroid Build Coastguard Worker {
766*7304104dSAndroid Build Coastguard Worker Dwarf_Word val;
767*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr;
768*7304104dSAndroid Build Coastguard Worker Dwarf_Die *die = &scopes[i];
769*7304104dSAndroid Build Coastguard Worker if (dwarf_tag (die) != DW_TAG_inlined_subroutine)
770*7304104dSAndroid Build Coastguard Worker continue;
771*7304104dSAndroid Build Coastguard Worker
772*7304104dSAndroid Build Coastguard Worker if (pretty)
773*7304104dSAndroid Build Coastguard Worker printf (" (inlined by) ");
774*7304104dSAndroid Build Coastguard Worker
775*7304104dSAndroid Build Coastguard Worker if (show_functions)
776*7304104dSAndroid Build Coastguard Worker {
777*7304104dSAndroid Build Coastguard Worker /* Search for the parent inline or function. It
778*7304104dSAndroid Build Coastguard Worker might not be directly above this inline -- e.g.
779*7304104dSAndroid Build Coastguard Worker there could be a lexical_block in between. */
780*7304104dSAndroid Build Coastguard Worker for (int j = i + 1; j < nscopes; j++)
781*7304104dSAndroid Build Coastguard Worker {
782*7304104dSAndroid Build Coastguard Worker Dwarf_Die *parent = &scopes[j];
783*7304104dSAndroid Build Coastguard Worker int tag = dwarf_tag (parent);
784*7304104dSAndroid Build Coastguard Worker if (tag == DW_TAG_inlined_subroutine
785*7304104dSAndroid Build Coastguard Worker || tag == DW_TAG_entry_point
786*7304104dSAndroid Build Coastguard Worker || tag == DW_TAG_subprogram)
787*7304104dSAndroid Build Coastguard Worker {
788*7304104dSAndroid Build Coastguard Worker printf ("%s%s",
789*7304104dSAndroid Build Coastguard Worker symname (get_diename (parent)),
790*7304104dSAndroid Build Coastguard Worker pretty ? " at " : "\n");
791*7304104dSAndroid Build Coastguard Worker break;
792*7304104dSAndroid Build Coastguard Worker }
793*7304104dSAndroid Build Coastguard Worker }
794*7304104dSAndroid Build Coastguard Worker }
795*7304104dSAndroid Build Coastguard Worker
796*7304104dSAndroid Build Coastguard Worker src = NULL;
797*7304104dSAndroid Build Coastguard Worker lineno = 0;
798*7304104dSAndroid Build Coastguard Worker linecol = 0;
799*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file,
800*7304104dSAndroid Build Coastguard Worker &attr), &val) == 0)
801*7304104dSAndroid Build Coastguard Worker src = dwarf_filesrc (files, val, NULL, NULL);
802*7304104dSAndroid Build Coastguard Worker
803*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
804*7304104dSAndroid Build Coastguard Worker &attr), &val) == 0)
805*7304104dSAndroid Build Coastguard Worker lineno = val;
806*7304104dSAndroid Build Coastguard Worker
807*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
808*7304104dSAndroid Build Coastguard Worker &attr), &val) == 0)
809*7304104dSAndroid Build Coastguard Worker linecol = val;
810*7304104dSAndroid Build Coastguard Worker
811*7304104dSAndroid Build Coastguard Worker if (src != NULL)
812*7304104dSAndroid Build Coastguard Worker {
813*7304104dSAndroid Build Coastguard Worker print_src (src, lineno, linecol, &cu);
814*7304104dSAndroid Build Coastguard Worker putchar ('\n');
815*7304104dSAndroid Build Coastguard Worker }
816*7304104dSAndroid Build Coastguard Worker else
817*7304104dSAndroid Build Coastguard Worker puts ("??:0");
818*7304104dSAndroid Build Coastguard Worker }
819*7304104dSAndroid Build Coastguard Worker }
820*7304104dSAndroid Build Coastguard Worker }
821*7304104dSAndroid Build Coastguard Worker }
822*7304104dSAndroid Build Coastguard Worker free (scopes);
823*7304104dSAndroid Build Coastguard Worker }
824*7304104dSAndroid Build Coastguard Worker
825*7304104dSAndroid Build Coastguard Worker return 0;
826*7304104dSAndroid Build Coastguard Worker }
827*7304104dSAndroid Build Coastguard Worker
828*7304104dSAndroid Build Coastguard Worker
829*7304104dSAndroid Build Coastguard Worker #include "debugpred.h"
830