xref: /aosp_15_r20/external/elfutils/src/addr2line.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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