1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker * Backtrace debugging
3*03f9172cSAndroid Build Coastguard Worker * Copyright (c) 2009, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker *
5*03f9172cSAndroid Build Coastguard Worker * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker */
8*03f9172cSAndroid Build Coastguard Worker
9*03f9172cSAndroid Build Coastguard Worker #ifdef WPA_TRACE_BFD
10*03f9172cSAndroid Build Coastguard Worker #define _GNU_SOURCE
11*03f9172cSAndroid Build Coastguard Worker #include <link.h>
12*03f9172cSAndroid Build Coastguard Worker #endif /* WPA_TRACE_BCD */
13*03f9172cSAndroid Build Coastguard Worker #include "includes.h"
14*03f9172cSAndroid Build Coastguard Worker
15*03f9172cSAndroid Build Coastguard Worker #include "common.h"
16*03f9172cSAndroid Build Coastguard Worker #include "trace.h"
17*03f9172cSAndroid Build Coastguard Worker
18*03f9172cSAndroid Build Coastguard Worker #ifdef WPA_TRACE
19*03f9172cSAndroid Build Coastguard Worker
20*03f9172cSAndroid Build Coastguard Worker static struct dl_list active_references =
21*03f9172cSAndroid Build Coastguard Worker { &active_references, &active_references };
22*03f9172cSAndroid Build Coastguard Worker
23*03f9172cSAndroid Build Coastguard Worker #ifdef WPA_TRACE_BFD
24*03f9172cSAndroid Build Coastguard Worker #include <bfd.h>
25*03f9172cSAndroid Build Coastguard Worker
26*03f9172cSAndroid Build Coastguard Worker #define DMGL_PARAMS (1 << 0)
27*03f9172cSAndroid Build Coastguard Worker #define DMGL_ANSI (1 << 1)
28*03f9172cSAndroid Build Coastguard Worker
29*03f9172cSAndroid Build Coastguard Worker static char *prg_fname = NULL;
30*03f9172cSAndroid Build Coastguard Worker static bfd *cached_abfd = NULL;
31*03f9172cSAndroid Build Coastguard Worker static asymbol **syms = NULL;
32*03f9172cSAndroid Build Coastguard Worker static unsigned long start_offset;
33*03f9172cSAndroid Build Coastguard Worker static int start_offset_looked_up;
34*03f9172cSAndroid Build Coastguard Worker
35*03f9172cSAndroid Build Coastguard Worker
callback(struct dl_phdr_info * info,size_t size,void * data)36*03f9172cSAndroid Build Coastguard Worker static int callback(struct dl_phdr_info *info, size_t size, void *data)
37*03f9172cSAndroid Build Coastguard Worker {
38*03f9172cSAndroid Build Coastguard Worker /*
39*03f9172cSAndroid Build Coastguard Worker * dl_iterate_phdr(3):
40*03f9172cSAndroid Build Coastguard Worker * "The first object visited by callback is the main program."
41*03f9172cSAndroid Build Coastguard Worker */
42*03f9172cSAndroid Build Coastguard Worker start_offset = info->dlpi_addr;
43*03f9172cSAndroid Build Coastguard Worker
44*03f9172cSAndroid Build Coastguard Worker /*
45*03f9172cSAndroid Build Coastguard Worker * dl_iterate_phdr(3):
46*03f9172cSAndroid Build Coastguard Worker * "The dl_iterate_phdr() function walks through the list of an
47*03f9172cSAndroid Build Coastguard Worker * application's shared objects and calls the function callback
48*03f9172cSAndroid Build Coastguard Worker * once for each object, until either all shared objects have
49*03f9172cSAndroid Build Coastguard Worker * been processed or callback returns a nonzero value."
50*03f9172cSAndroid Build Coastguard Worker */
51*03f9172cSAndroid Build Coastguard Worker return 1;
52*03f9172cSAndroid Build Coastguard Worker }
53*03f9172cSAndroid Build Coastguard Worker
54*03f9172cSAndroid Build Coastguard Worker
get_prg_fname(void)55*03f9172cSAndroid Build Coastguard Worker static void get_prg_fname(void)
56*03f9172cSAndroid Build Coastguard Worker {
57*03f9172cSAndroid Build Coastguard Worker char exe[50], fname[512];
58*03f9172cSAndroid Build Coastguard Worker int len;
59*03f9172cSAndroid Build Coastguard Worker os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid());
60*03f9172cSAndroid Build Coastguard Worker len = readlink(exe, fname, sizeof(fname) - 1);
61*03f9172cSAndroid Build Coastguard Worker if (len < 0 || len >= (int) sizeof(fname)) {
62*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_ERROR, "readlink: %s", strerror(errno));
63*03f9172cSAndroid Build Coastguard Worker return;
64*03f9172cSAndroid Build Coastguard Worker }
65*03f9172cSAndroid Build Coastguard Worker fname[len] = '\0';
66*03f9172cSAndroid Build Coastguard Worker prg_fname = strdup(fname);
67*03f9172cSAndroid Build Coastguard Worker }
68*03f9172cSAndroid Build Coastguard Worker
69*03f9172cSAndroid Build Coastguard Worker
open_bfd(const char * fname)70*03f9172cSAndroid Build Coastguard Worker static bfd * open_bfd(const char *fname)
71*03f9172cSAndroid Build Coastguard Worker {
72*03f9172cSAndroid Build Coastguard Worker bfd *abfd;
73*03f9172cSAndroid Build Coastguard Worker char **matching;
74*03f9172cSAndroid Build Coastguard Worker
75*03f9172cSAndroid Build Coastguard Worker abfd = bfd_openr(prg_fname, NULL);
76*03f9172cSAndroid Build Coastguard Worker if (abfd == NULL) {
77*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "bfd_openr failed");
78*03f9172cSAndroid Build Coastguard Worker return NULL;
79*03f9172cSAndroid Build Coastguard Worker }
80*03f9172cSAndroid Build Coastguard Worker
81*03f9172cSAndroid Build Coastguard Worker if (bfd_check_format(abfd, bfd_archive)) {
82*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "bfd_check_format failed");
83*03f9172cSAndroid Build Coastguard Worker bfd_close(abfd);
84*03f9172cSAndroid Build Coastguard Worker return NULL;
85*03f9172cSAndroid Build Coastguard Worker }
86*03f9172cSAndroid Build Coastguard Worker
87*03f9172cSAndroid Build Coastguard Worker if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
88*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "bfd_check_format_matches failed");
89*03f9172cSAndroid Build Coastguard Worker free(matching);
90*03f9172cSAndroid Build Coastguard Worker bfd_close(abfd);
91*03f9172cSAndroid Build Coastguard Worker return NULL;
92*03f9172cSAndroid Build Coastguard Worker }
93*03f9172cSAndroid Build Coastguard Worker
94*03f9172cSAndroid Build Coastguard Worker return abfd;
95*03f9172cSAndroid Build Coastguard Worker }
96*03f9172cSAndroid Build Coastguard Worker
97*03f9172cSAndroid Build Coastguard Worker
read_syms(bfd * abfd)98*03f9172cSAndroid Build Coastguard Worker static void read_syms(bfd *abfd)
99*03f9172cSAndroid Build Coastguard Worker {
100*03f9172cSAndroid Build Coastguard Worker long storage, symcount;
101*03f9172cSAndroid Build Coastguard Worker bfd_boolean dynamic = FALSE;
102*03f9172cSAndroid Build Coastguard Worker
103*03f9172cSAndroid Build Coastguard Worker if (syms)
104*03f9172cSAndroid Build Coastguard Worker return;
105*03f9172cSAndroid Build Coastguard Worker
106*03f9172cSAndroid Build Coastguard Worker if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) {
107*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "No symbols");
108*03f9172cSAndroid Build Coastguard Worker return;
109*03f9172cSAndroid Build Coastguard Worker }
110*03f9172cSAndroid Build Coastguard Worker
111*03f9172cSAndroid Build Coastguard Worker storage = bfd_get_symtab_upper_bound(abfd);
112*03f9172cSAndroid Build Coastguard Worker if (storage == 0) {
113*03f9172cSAndroid Build Coastguard Worker storage = bfd_get_dynamic_symtab_upper_bound(abfd);
114*03f9172cSAndroid Build Coastguard Worker dynamic = TRUE;
115*03f9172cSAndroid Build Coastguard Worker }
116*03f9172cSAndroid Build Coastguard Worker if (storage < 0) {
117*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "Unknown symtab upper bound");
118*03f9172cSAndroid Build Coastguard Worker return;
119*03f9172cSAndroid Build Coastguard Worker }
120*03f9172cSAndroid Build Coastguard Worker
121*03f9172cSAndroid Build Coastguard Worker syms = malloc(storage);
122*03f9172cSAndroid Build Coastguard Worker if (syms == NULL) {
123*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "Failed to allocate memory for symtab "
124*03f9172cSAndroid Build Coastguard Worker "(%ld bytes)", storage);
125*03f9172cSAndroid Build Coastguard Worker return;
126*03f9172cSAndroid Build Coastguard Worker }
127*03f9172cSAndroid Build Coastguard Worker if (dynamic)
128*03f9172cSAndroid Build Coastguard Worker symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
129*03f9172cSAndroid Build Coastguard Worker else
130*03f9172cSAndroid Build Coastguard Worker symcount = bfd_canonicalize_symtab(abfd, syms);
131*03f9172cSAndroid Build Coastguard Worker if (symcount < 0) {
132*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab",
133*03f9172cSAndroid Build Coastguard Worker dynamic ? "dynamic " : "");
134*03f9172cSAndroid Build Coastguard Worker free(syms);
135*03f9172cSAndroid Build Coastguard Worker syms = NULL;
136*03f9172cSAndroid Build Coastguard Worker return;
137*03f9172cSAndroid Build Coastguard Worker }
138*03f9172cSAndroid Build Coastguard Worker }
139*03f9172cSAndroid Build Coastguard Worker
140*03f9172cSAndroid Build Coastguard Worker
141*03f9172cSAndroid Build Coastguard Worker struct bfd_data {
142*03f9172cSAndroid Build Coastguard Worker bfd_vma pc;
143*03f9172cSAndroid Build Coastguard Worker bfd_boolean found;
144*03f9172cSAndroid Build Coastguard Worker const char *filename;
145*03f9172cSAndroid Build Coastguard Worker const char *function;
146*03f9172cSAndroid Build Coastguard Worker unsigned int line;
147*03f9172cSAndroid Build Coastguard Worker };
148*03f9172cSAndroid Build Coastguard Worker
149*03f9172cSAndroid Build Coastguard Worker /*
150*03f9172cSAndroid Build Coastguard Worker * binutils removed the bfd parameter and renamed things but
151*03f9172cSAndroid Build Coastguard Worker * those were macros so we can detect their absence.
152*03f9172cSAndroid Build Coastguard Worker * Cf. https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=fd3619828e94a24a92cddec42cbc0ab33352eeb4;hp=5dfda3562a69686c43aad4fb0269cc9d5ec010d5
153*03f9172cSAndroid Build Coastguard Worker */
154*03f9172cSAndroid Build Coastguard Worker #ifndef bfd_get_section_vma
155*03f9172cSAndroid Build Coastguard Worker #define bfd_get_section_vma(bfd, section) bfd_section_vma(section)
156*03f9172cSAndroid Build Coastguard Worker #endif
157*03f9172cSAndroid Build Coastguard Worker #ifndef bfd_get_section_size
158*03f9172cSAndroid Build Coastguard Worker #define bfd_get_section_size bfd_section_size
159*03f9172cSAndroid Build Coastguard Worker #endif
160*03f9172cSAndroid Build Coastguard Worker
find_addr_sect(bfd * abfd,asection * section,void * obj)161*03f9172cSAndroid Build Coastguard Worker static void find_addr_sect(bfd *abfd, asection *section, void *obj)
162*03f9172cSAndroid Build Coastguard Worker {
163*03f9172cSAndroid Build Coastguard Worker struct bfd_data *data = obj;
164*03f9172cSAndroid Build Coastguard Worker bfd_vma vma;
165*03f9172cSAndroid Build Coastguard Worker bfd_size_type size;
166*03f9172cSAndroid Build Coastguard Worker
167*03f9172cSAndroid Build Coastguard Worker if (data->found)
168*03f9172cSAndroid Build Coastguard Worker return;
169*03f9172cSAndroid Build Coastguard Worker
170*03f9172cSAndroid Build Coastguard Worker if (!(bfd_get_section_vma(abfd, section)))
171*03f9172cSAndroid Build Coastguard Worker return;
172*03f9172cSAndroid Build Coastguard Worker
173*03f9172cSAndroid Build Coastguard Worker vma = bfd_get_section_vma(abfd, section);
174*03f9172cSAndroid Build Coastguard Worker if (data->pc < vma)
175*03f9172cSAndroid Build Coastguard Worker return;
176*03f9172cSAndroid Build Coastguard Worker
177*03f9172cSAndroid Build Coastguard Worker size = bfd_get_section_size(section);
178*03f9172cSAndroid Build Coastguard Worker if (data->pc >= vma + size)
179*03f9172cSAndroid Build Coastguard Worker return;
180*03f9172cSAndroid Build Coastguard Worker
181*03f9172cSAndroid Build Coastguard Worker data->found = bfd_find_nearest_line(abfd, section, syms,
182*03f9172cSAndroid Build Coastguard Worker data->pc - vma,
183*03f9172cSAndroid Build Coastguard Worker &data->filename,
184*03f9172cSAndroid Build Coastguard Worker &data->function,
185*03f9172cSAndroid Build Coastguard Worker &data->line);
186*03f9172cSAndroid Build Coastguard Worker }
187*03f9172cSAndroid Build Coastguard Worker
188*03f9172cSAndroid Build Coastguard Worker
wpa_trace_bfd_addr(void * pc)189*03f9172cSAndroid Build Coastguard Worker static void wpa_trace_bfd_addr(void *pc)
190*03f9172cSAndroid Build Coastguard Worker {
191*03f9172cSAndroid Build Coastguard Worker bfd *abfd = cached_abfd;
192*03f9172cSAndroid Build Coastguard Worker struct bfd_data data;
193*03f9172cSAndroid Build Coastguard Worker const char *name;
194*03f9172cSAndroid Build Coastguard Worker char *aname = NULL;
195*03f9172cSAndroid Build Coastguard Worker const char *filename;
196*03f9172cSAndroid Build Coastguard Worker
197*03f9172cSAndroid Build Coastguard Worker if (abfd == NULL)
198*03f9172cSAndroid Build Coastguard Worker return;
199*03f9172cSAndroid Build Coastguard Worker
200*03f9172cSAndroid Build Coastguard Worker data.pc = (uintptr_t) ((u8 *) pc - start_offset);
201*03f9172cSAndroid Build Coastguard Worker data.found = FALSE;
202*03f9172cSAndroid Build Coastguard Worker bfd_map_over_sections(abfd, find_addr_sect, &data);
203*03f9172cSAndroid Build Coastguard Worker
204*03f9172cSAndroid Build Coastguard Worker if (!data.found)
205*03f9172cSAndroid Build Coastguard Worker return;
206*03f9172cSAndroid Build Coastguard Worker
207*03f9172cSAndroid Build Coastguard Worker do {
208*03f9172cSAndroid Build Coastguard Worker if (data.function)
209*03f9172cSAndroid Build Coastguard Worker aname = bfd_demangle(abfd, data.function,
210*03f9172cSAndroid Build Coastguard Worker DMGL_ANSI | DMGL_PARAMS);
211*03f9172cSAndroid Build Coastguard Worker name = aname ? aname : data.function;
212*03f9172cSAndroid Build Coastguard Worker filename = data.filename;
213*03f9172cSAndroid Build Coastguard Worker if (filename) {
214*03f9172cSAndroid Build Coastguard Worker char *end = os_strrchr(filename, '/');
215*03f9172cSAndroid Build Coastguard Worker int i = 0;
216*03f9172cSAndroid Build Coastguard Worker while (*filename && *filename == prg_fname[i] &&
217*03f9172cSAndroid Build Coastguard Worker filename <= end) {
218*03f9172cSAndroid Build Coastguard Worker filename++;
219*03f9172cSAndroid Build Coastguard Worker i++;
220*03f9172cSAndroid Build Coastguard Worker }
221*03f9172cSAndroid Build Coastguard Worker }
222*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, " %s() %s:%u",
223*03f9172cSAndroid Build Coastguard Worker name, filename, data.line);
224*03f9172cSAndroid Build Coastguard Worker free(aname);
225*03f9172cSAndroid Build Coastguard Worker aname = NULL;
226*03f9172cSAndroid Build Coastguard Worker
227*03f9172cSAndroid Build Coastguard Worker data.found = bfd_find_inliner_info(abfd, &data.filename,
228*03f9172cSAndroid Build Coastguard Worker &data.function, &data.line);
229*03f9172cSAndroid Build Coastguard Worker } while (data.found);
230*03f9172cSAndroid Build Coastguard Worker }
231*03f9172cSAndroid Build Coastguard Worker
232*03f9172cSAndroid Build Coastguard Worker
wpa_trace_bfd_addr2func(void * pc)233*03f9172cSAndroid Build Coastguard Worker static const char * wpa_trace_bfd_addr2func(void *pc)
234*03f9172cSAndroid Build Coastguard Worker {
235*03f9172cSAndroid Build Coastguard Worker bfd *abfd = cached_abfd;
236*03f9172cSAndroid Build Coastguard Worker struct bfd_data data;
237*03f9172cSAndroid Build Coastguard Worker
238*03f9172cSAndroid Build Coastguard Worker if (abfd == NULL)
239*03f9172cSAndroid Build Coastguard Worker return NULL;
240*03f9172cSAndroid Build Coastguard Worker
241*03f9172cSAndroid Build Coastguard Worker data.pc = (uintptr_t) ((u8 *) pc - start_offset);
242*03f9172cSAndroid Build Coastguard Worker data.found = FALSE;
243*03f9172cSAndroid Build Coastguard Worker bfd_map_over_sections(abfd, find_addr_sect, &data);
244*03f9172cSAndroid Build Coastguard Worker
245*03f9172cSAndroid Build Coastguard Worker if (!data.found)
246*03f9172cSAndroid Build Coastguard Worker return NULL;
247*03f9172cSAndroid Build Coastguard Worker
248*03f9172cSAndroid Build Coastguard Worker return data.function;
249*03f9172cSAndroid Build Coastguard Worker }
250*03f9172cSAndroid Build Coastguard Worker
251*03f9172cSAndroid Build Coastguard Worker
wpa_trace_bfd_init(void)252*03f9172cSAndroid Build Coastguard Worker static void wpa_trace_bfd_init(void)
253*03f9172cSAndroid Build Coastguard Worker {
254*03f9172cSAndroid Build Coastguard Worker if (!prg_fname) {
255*03f9172cSAndroid Build Coastguard Worker get_prg_fname();
256*03f9172cSAndroid Build Coastguard Worker if (!prg_fname)
257*03f9172cSAndroid Build Coastguard Worker return;
258*03f9172cSAndroid Build Coastguard Worker }
259*03f9172cSAndroid Build Coastguard Worker
260*03f9172cSAndroid Build Coastguard Worker if (!cached_abfd) {
261*03f9172cSAndroid Build Coastguard Worker cached_abfd = open_bfd(prg_fname);
262*03f9172cSAndroid Build Coastguard Worker if (!cached_abfd) {
263*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "Failed to open bfd");
264*03f9172cSAndroid Build Coastguard Worker return;
265*03f9172cSAndroid Build Coastguard Worker }
266*03f9172cSAndroid Build Coastguard Worker }
267*03f9172cSAndroid Build Coastguard Worker
268*03f9172cSAndroid Build Coastguard Worker read_syms(cached_abfd);
269*03f9172cSAndroid Build Coastguard Worker if (!syms) {
270*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "Failed to read symbols");
271*03f9172cSAndroid Build Coastguard Worker return;
272*03f9172cSAndroid Build Coastguard Worker }
273*03f9172cSAndroid Build Coastguard Worker
274*03f9172cSAndroid Build Coastguard Worker if (!start_offset_looked_up) {
275*03f9172cSAndroid Build Coastguard Worker dl_iterate_phdr(callback, NULL);
276*03f9172cSAndroid Build Coastguard Worker start_offset_looked_up = 1;
277*03f9172cSAndroid Build Coastguard Worker }
278*03f9172cSAndroid Build Coastguard Worker }
279*03f9172cSAndroid Build Coastguard Worker
280*03f9172cSAndroid Build Coastguard Worker
wpa_trace_dump_funcname(const char * title,void * pc)281*03f9172cSAndroid Build Coastguard Worker void wpa_trace_dump_funcname(const char *title, void *pc)
282*03f9172cSAndroid Build Coastguard Worker {
283*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc);
284*03f9172cSAndroid Build Coastguard Worker wpa_trace_bfd_init();
285*03f9172cSAndroid Build Coastguard Worker wpa_trace_bfd_addr(pc);
286*03f9172cSAndroid Build Coastguard Worker }
287*03f9172cSAndroid Build Coastguard Worker
288*03f9172cSAndroid Build Coastguard Worker
wpa_trace_calling_func(const char * buf[],size_t len)289*03f9172cSAndroid Build Coastguard Worker size_t wpa_trace_calling_func(const char *buf[], size_t len)
290*03f9172cSAndroid Build Coastguard Worker {
291*03f9172cSAndroid Build Coastguard Worker bfd *abfd;
292*03f9172cSAndroid Build Coastguard Worker void *btrace_res[WPA_TRACE_LEN];
293*03f9172cSAndroid Build Coastguard Worker int i, btrace_num;
294*03f9172cSAndroid Build Coastguard Worker size_t pos = 0;
295*03f9172cSAndroid Build Coastguard Worker
296*03f9172cSAndroid Build Coastguard Worker if (len == 0)
297*03f9172cSAndroid Build Coastguard Worker return 0;
298*03f9172cSAndroid Build Coastguard Worker if (len > WPA_TRACE_LEN)
299*03f9172cSAndroid Build Coastguard Worker len = WPA_TRACE_LEN;
300*03f9172cSAndroid Build Coastguard Worker
301*03f9172cSAndroid Build Coastguard Worker wpa_trace_bfd_init();
302*03f9172cSAndroid Build Coastguard Worker abfd = cached_abfd;
303*03f9172cSAndroid Build Coastguard Worker if (!abfd)
304*03f9172cSAndroid Build Coastguard Worker return 0;
305*03f9172cSAndroid Build Coastguard Worker
306*03f9172cSAndroid Build Coastguard Worker btrace_num = backtrace(btrace_res, len);
307*03f9172cSAndroid Build Coastguard Worker if (btrace_num < 1)
308*03f9172cSAndroid Build Coastguard Worker return 0;
309*03f9172cSAndroid Build Coastguard Worker
310*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < btrace_num; i++) {
311*03f9172cSAndroid Build Coastguard Worker struct bfd_data data;
312*03f9172cSAndroid Build Coastguard Worker
313*03f9172cSAndroid Build Coastguard Worker data.pc = (uintptr_t) ((u8 *) btrace_res[i] - start_offset);
314*03f9172cSAndroid Build Coastguard Worker data.found = FALSE;
315*03f9172cSAndroid Build Coastguard Worker bfd_map_over_sections(abfd, find_addr_sect, &data);
316*03f9172cSAndroid Build Coastguard Worker
317*03f9172cSAndroid Build Coastguard Worker while (data.found) {
318*03f9172cSAndroid Build Coastguard Worker if (data.function &&
319*03f9172cSAndroid Build Coastguard Worker (pos > 0 ||
320*03f9172cSAndroid Build Coastguard Worker os_strcmp(data.function, __func__) != 0)) {
321*03f9172cSAndroid Build Coastguard Worker buf[pos++] = data.function;
322*03f9172cSAndroid Build Coastguard Worker if (pos == len)
323*03f9172cSAndroid Build Coastguard Worker return pos;
324*03f9172cSAndroid Build Coastguard Worker }
325*03f9172cSAndroid Build Coastguard Worker
326*03f9172cSAndroid Build Coastguard Worker data.found = bfd_find_inliner_info(abfd, &data.filename,
327*03f9172cSAndroid Build Coastguard Worker &data.function,
328*03f9172cSAndroid Build Coastguard Worker &data.line);
329*03f9172cSAndroid Build Coastguard Worker }
330*03f9172cSAndroid Build Coastguard Worker }
331*03f9172cSAndroid Build Coastguard Worker
332*03f9172cSAndroid Build Coastguard Worker return pos;
333*03f9172cSAndroid Build Coastguard Worker }
334*03f9172cSAndroid Build Coastguard Worker
335*03f9172cSAndroid Build Coastguard Worker #else /* WPA_TRACE_BFD */
336*03f9172cSAndroid Build Coastguard Worker
337*03f9172cSAndroid Build Coastguard Worker #define wpa_trace_bfd_init() do { } while (0)
338*03f9172cSAndroid Build Coastguard Worker #define wpa_trace_bfd_addr(pc) do { } while (0)
339*03f9172cSAndroid Build Coastguard Worker #define wpa_trace_bfd_addr2func(pc) NULL
340*03f9172cSAndroid Build Coastguard Worker
341*03f9172cSAndroid Build Coastguard Worker #endif /* WPA_TRACE_BFD */
342*03f9172cSAndroid Build Coastguard Worker
wpa_trace_dump_func(const char * title,void ** btrace,int btrace_num)343*03f9172cSAndroid Build Coastguard Worker void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
344*03f9172cSAndroid Build Coastguard Worker {
345*03f9172cSAndroid Build Coastguard Worker char **sym;
346*03f9172cSAndroid Build Coastguard Worker int i;
347*03f9172cSAndroid Build Coastguard Worker enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state;
348*03f9172cSAndroid Build Coastguard Worker
349*03f9172cSAndroid Build Coastguard Worker wpa_trace_bfd_init();
350*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title);
351*03f9172cSAndroid Build Coastguard Worker sym = backtrace_symbols(btrace, btrace_num);
352*03f9172cSAndroid Build Coastguard Worker state = TRACE_HEAD;
353*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < btrace_num; i++) {
354*03f9172cSAndroid Build Coastguard Worker const char *func = wpa_trace_bfd_addr2func(btrace[i]);
355*03f9172cSAndroid Build Coastguard Worker if (state == TRACE_HEAD && func &&
356*03f9172cSAndroid Build Coastguard Worker (os_strcmp(func, "wpa_trace_add_ref_func") == 0 ||
357*03f9172cSAndroid Build Coastguard Worker os_strcmp(func, "wpa_trace_check_ref") == 0 ||
358*03f9172cSAndroid Build Coastguard Worker os_strcmp(func, "wpa_trace_show") == 0))
359*03f9172cSAndroid Build Coastguard Worker continue;
360*03f9172cSAndroid Build Coastguard Worker if (state == TRACE_TAIL && sym && sym[i] &&
361*03f9172cSAndroid Build Coastguard Worker os_strstr(sym[i], "__libc_start_main"))
362*03f9172cSAndroid Build Coastguard Worker break;
363*03f9172cSAndroid Build Coastguard Worker if (state == TRACE_HEAD)
364*03f9172cSAndroid Build Coastguard Worker state = TRACE_RELEVANT;
365*03f9172cSAndroid Build Coastguard Worker if (sym)
366*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]);
367*03f9172cSAndroid Build Coastguard Worker else
368*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]);
369*03f9172cSAndroid Build Coastguard Worker wpa_trace_bfd_addr(btrace[i]);
370*03f9172cSAndroid Build Coastguard Worker if (state == TRACE_RELEVANT && func &&
371*03f9172cSAndroid Build Coastguard Worker os_strcmp(func, "main") == 0)
372*03f9172cSAndroid Build Coastguard Worker state = TRACE_TAIL;
373*03f9172cSAndroid Build Coastguard Worker }
374*03f9172cSAndroid Build Coastguard Worker free(sym);
375*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title);
376*03f9172cSAndroid Build Coastguard Worker }
377*03f9172cSAndroid Build Coastguard Worker
378*03f9172cSAndroid Build Coastguard Worker
wpa_trace_show(const char * title)379*03f9172cSAndroid Build Coastguard Worker void wpa_trace_show(const char *title)
380*03f9172cSAndroid Build Coastguard Worker {
381*03f9172cSAndroid Build Coastguard Worker struct info {
382*03f9172cSAndroid Build Coastguard Worker WPA_TRACE_INFO
383*03f9172cSAndroid Build Coastguard Worker } info;
384*03f9172cSAndroid Build Coastguard Worker wpa_trace_record(&info);
385*03f9172cSAndroid Build Coastguard Worker wpa_trace_dump(title, &info);
386*03f9172cSAndroid Build Coastguard Worker }
387*03f9172cSAndroid Build Coastguard Worker
388*03f9172cSAndroid Build Coastguard Worker
wpa_trace_add_ref_func(struct wpa_trace_ref * ref,const void * addr)389*03f9172cSAndroid Build Coastguard Worker void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr)
390*03f9172cSAndroid Build Coastguard Worker {
391*03f9172cSAndroid Build Coastguard Worker if (addr == NULL)
392*03f9172cSAndroid Build Coastguard Worker return;
393*03f9172cSAndroid Build Coastguard Worker ref->addr = addr;
394*03f9172cSAndroid Build Coastguard Worker wpa_trace_record(ref);
395*03f9172cSAndroid Build Coastguard Worker dl_list_add(&active_references, &ref->list);
396*03f9172cSAndroid Build Coastguard Worker }
397*03f9172cSAndroid Build Coastguard Worker
398*03f9172cSAndroid Build Coastguard Worker
wpa_trace_check_ref(const void * addr)399*03f9172cSAndroid Build Coastguard Worker void wpa_trace_check_ref(const void *addr)
400*03f9172cSAndroid Build Coastguard Worker {
401*03f9172cSAndroid Build Coastguard Worker struct wpa_trace_ref *ref;
402*03f9172cSAndroid Build Coastguard Worker dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) {
403*03f9172cSAndroid Build Coastguard Worker if (addr != ref->addr)
404*03f9172cSAndroid Build Coastguard Worker continue;
405*03f9172cSAndroid Build Coastguard Worker wpa_trace_show("Freeing referenced memory");
406*03f9172cSAndroid Build Coastguard Worker wpa_trace_dump("Reference registration", ref);
407*03f9172cSAndroid Build Coastguard Worker abort();
408*03f9172cSAndroid Build Coastguard Worker }
409*03f9172cSAndroid Build Coastguard Worker }
410*03f9172cSAndroid Build Coastguard Worker
411*03f9172cSAndroid Build Coastguard Worker
wpa_trace_deinit(void)412*03f9172cSAndroid Build Coastguard Worker void wpa_trace_deinit(void)
413*03f9172cSAndroid Build Coastguard Worker {
414*03f9172cSAndroid Build Coastguard Worker #ifdef WPA_TRACE_BFD
415*03f9172cSAndroid Build Coastguard Worker free(syms);
416*03f9172cSAndroid Build Coastguard Worker syms = NULL;
417*03f9172cSAndroid Build Coastguard Worker #endif /* WPA_TRACE_BFD */
418*03f9172cSAndroid Build Coastguard Worker }
419*03f9172cSAndroid Build Coastguard Worker
420*03f9172cSAndroid Build Coastguard Worker #endif /* WPA_TRACE */
421