xref: /aosp_15_r20/external/wpa_supplicant_8/src/utils/trace.c (revision 03f9172ca588f91df233974f4258bab95191f931)
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