xref: /dflybsd-src/contrib/wpa_supplicant/src/utils/trace.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
13ff40c12SJohn Marino /*
23ff40c12SJohn Marino  * Backtrace debugging
33ff40c12SJohn Marino  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
43ff40c12SJohn Marino  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
73ff40c12SJohn Marino  */
83ff40c12SJohn Marino 
9*a1157835SDaniel Fojt #ifdef WPA_TRACE_BFD
10*a1157835SDaniel Fojt #define _GNU_SOURCE
11*a1157835SDaniel Fojt #include <link.h>
12*a1157835SDaniel Fojt #endif /* WPA_TRACE_BCD */
133ff40c12SJohn Marino #include "includes.h"
143ff40c12SJohn Marino 
153ff40c12SJohn Marino #include "common.h"
163ff40c12SJohn Marino #include "trace.h"
173ff40c12SJohn Marino 
183ff40c12SJohn Marino #ifdef WPA_TRACE
193ff40c12SJohn Marino 
203ff40c12SJohn Marino static struct dl_list active_references =
213ff40c12SJohn Marino { &active_references, &active_references };
223ff40c12SJohn Marino 
233ff40c12SJohn Marino #ifdef WPA_TRACE_BFD
243ff40c12SJohn Marino #include <bfd.h>
25*a1157835SDaniel Fojt 
26*a1157835SDaniel Fojt #define DMGL_PARAMS      (1 << 0)
27*a1157835SDaniel Fojt #define DMGL_ANSI        (1 << 1)
283ff40c12SJohn Marino 
293ff40c12SJohn Marino static char *prg_fname = NULL;
303ff40c12SJohn Marino static bfd *cached_abfd = NULL;
313ff40c12SJohn Marino static asymbol **syms = NULL;
32*a1157835SDaniel Fojt static unsigned long start_offset;
33*a1157835SDaniel Fojt static int start_offset_looked_up;
34*a1157835SDaniel Fojt 
35*a1157835SDaniel Fojt 
callback(struct dl_phdr_info * info,size_t size,void * data)36*a1157835SDaniel Fojt static int callback(struct dl_phdr_info *info, size_t size, void *data)
37*a1157835SDaniel Fojt {
38*a1157835SDaniel Fojt 	/*
39*a1157835SDaniel Fojt 	 * dl_iterate_phdr(3):
40*a1157835SDaniel Fojt 	 * "The first object visited by callback is the main program."
41*a1157835SDaniel Fojt 	 */
42*a1157835SDaniel Fojt 	start_offset = info->dlpi_addr;
43*a1157835SDaniel Fojt 
44*a1157835SDaniel Fojt 	/*
45*a1157835SDaniel Fojt 	 * dl_iterate_phdr(3):
46*a1157835SDaniel Fojt 	 * "The dl_iterate_phdr() function walks through the list of an
47*a1157835SDaniel Fojt 	 *  application's shared objects and calls the function callback
48*a1157835SDaniel Fojt 	 *  once for each object, until either all shared objects have
49*a1157835SDaniel Fojt 	 *  been processed or callback returns a nonzero value."
50*a1157835SDaniel Fojt 	 */
51*a1157835SDaniel Fojt 	return 1;
52*a1157835SDaniel Fojt }
53*a1157835SDaniel Fojt 
543ff40c12SJohn Marino 
get_prg_fname(void)553ff40c12SJohn Marino static void get_prg_fname(void)
563ff40c12SJohn Marino {
573ff40c12SJohn Marino 	char exe[50], fname[512];
583ff40c12SJohn Marino 	int len;
593ff40c12SJohn Marino 	os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid());
603ff40c12SJohn Marino 	len = readlink(exe, fname, sizeof(fname) - 1);
613ff40c12SJohn Marino 	if (len < 0 || len >= (int) sizeof(fname)) {
62*a1157835SDaniel Fojt 		wpa_printf(MSG_ERROR, "readlink: %s", strerror(errno));
633ff40c12SJohn Marino 		return;
643ff40c12SJohn Marino 	}
653ff40c12SJohn Marino 	fname[len] = '\0';
663ff40c12SJohn Marino 	prg_fname = strdup(fname);
673ff40c12SJohn Marino }
683ff40c12SJohn Marino 
693ff40c12SJohn Marino 
open_bfd(const char * fname)703ff40c12SJohn Marino static bfd * open_bfd(const char *fname)
713ff40c12SJohn Marino {
723ff40c12SJohn Marino 	bfd *abfd;
733ff40c12SJohn Marino 	char **matching;
743ff40c12SJohn Marino 
753ff40c12SJohn Marino 	abfd = bfd_openr(prg_fname, NULL);
763ff40c12SJohn Marino 	if (abfd == NULL) {
773ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "bfd_openr failed");
783ff40c12SJohn Marino 		return NULL;
793ff40c12SJohn Marino 	}
803ff40c12SJohn Marino 
813ff40c12SJohn Marino 	if (bfd_check_format(abfd, bfd_archive)) {
823ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "bfd_check_format failed");
833ff40c12SJohn Marino 		bfd_close(abfd);
843ff40c12SJohn Marino 		return NULL;
853ff40c12SJohn Marino 	}
863ff40c12SJohn Marino 
873ff40c12SJohn Marino 	if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
883ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "bfd_check_format_matches failed");
893ff40c12SJohn Marino 		free(matching);
903ff40c12SJohn Marino 		bfd_close(abfd);
913ff40c12SJohn Marino 		return NULL;
923ff40c12SJohn Marino 	}
933ff40c12SJohn Marino 
943ff40c12SJohn Marino 	return abfd;
953ff40c12SJohn Marino }
963ff40c12SJohn Marino 
973ff40c12SJohn Marino 
read_syms(bfd * abfd)983ff40c12SJohn Marino static void read_syms(bfd *abfd)
993ff40c12SJohn Marino {
1003ff40c12SJohn Marino 	long storage, symcount;
1013ff40c12SJohn Marino 	bfd_boolean dynamic = FALSE;
1023ff40c12SJohn Marino 
1033ff40c12SJohn Marino 	if (syms)
1043ff40c12SJohn Marino 		return;
1053ff40c12SJohn Marino 
1063ff40c12SJohn Marino 	if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) {
1073ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "No symbols");
1083ff40c12SJohn Marino 		return;
1093ff40c12SJohn Marino 	}
1103ff40c12SJohn Marino 
1113ff40c12SJohn Marino 	storage = bfd_get_symtab_upper_bound(abfd);
1123ff40c12SJohn Marino 	if (storage == 0) {
1133ff40c12SJohn Marino 		storage = bfd_get_dynamic_symtab_upper_bound(abfd);
1143ff40c12SJohn Marino 		dynamic = TRUE;
1153ff40c12SJohn Marino 	}
1163ff40c12SJohn Marino 	if (storage < 0) {
1173ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "Unknown symtab upper bound");
1183ff40c12SJohn Marino 		return;
1193ff40c12SJohn Marino 	}
1203ff40c12SJohn Marino 
1213ff40c12SJohn Marino 	syms = malloc(storage);
1223ff40c12SJohn Marino 	if (syms == NULL) {
1233ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "Failed to allocate memory for symtab "
1243ff40c12SJohn Marino 			   "(%ld bytes)", storage);
1253ff40c12SJohn Marino 		return;
1263ff40c12SJohn Marino 	}
1273ff40c12SJohn Marino 	if (dynamic)
1283ff40c12SJohn Marino 		symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
1293ff40c12SJohn Marino 	else
1303ff40c12SJohn Marino 		symcount = bfd_canonicalize_symtab(abfd, syms);
1313ff40c12SJohn Marino 	if (symcount < 0) {
1323ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab",
1333ff40c12SJohn Marino 			   dynamic ? "dynamic " : "");
1343ff40c12SJohn Marino 		free(syms);
1353ff40c12SJohn Marino 		syms = NULL;
1363ff40c12SJohn Marino 		return;
1373ff40c12SJohn Marino 	}
1383ff40c12SJohn Marino }
1393ff40c12SJohn Marino 
1403ff40c12SJohn Marino 
1413ff40c12SJohn Marino struct bfd_data {
1423ff40c12SJohn Marino 	bfd_vma pc;
1433ff40c12SJohn Marino 	bfd_boolean found;
1443ff40c12SJohn Marino 	const char *filename;
1453ff40c12SJohn Marino 	const char *function;
1463ff40c12SJohn Marino 	unsigned int line;
1473ff40c12SJohn Marino };
1483ff40c12SJohn Marino 
1493ff40c12SJohn Marino 
find_addr_sect(bfd * abfd,asection * section,void * obj)1503ff40c12SJohn Marino static void find_addr_sect(bfd *abfd, asection *section, void *obj)
1513ff40c12SJohn Marino {
1523ff40c12SJohn Marino 	struct bfd_data *data = obj;
1533ff40c12SJohn Marino 	bfd_vma vma;
1543ff40c12SJohn Marino 	bfd_size_type size;
1553ff40c12SJohn Marino 
1563ff40c12SJohn Marino 	if (data->found)
1573ff40c12SJohn Marino 		return;
1583ff40c12SJohn Marino 
1593ff40c12SJohn Marino 	if (!(bfd_get_section_vma(abfd, section)))
1603ff40c12SJohn Marino 		return;
1613ff40c12SJohn Marino 
1623ff40c12SJohn Marino 	vma = bfd_get_section_vma(abfd, section);
1633ff40c12SJohn Marino 	if (data->pc < vma)
1643ff40c12SJohn Marino 		return;
1653ff40c12SJohn Marino 
1663ff40c12SJohn Marino 	size = bfd_get_section_size(section);
1673ff40c12SJohn Marino 	if (data->pc >= vma + size)
1683ff40c12SJohn Marino 		return;
1693ff40c12SJohn Marino 
1703ff40c12SJohn Marino 	data->found = bfd_find_nearest_line(abfd, section, syms,
1713ff40c12SJohn Marino 					    data->pc - vma,
1723ff40c12SJohn Marino 					    &data->filename,
1733ff40c12SJohn Marino 					    &data->function,
1743ff40c12SJohn Marino 					    &data->line);
1753ff40c12SJohn Marino }
1763ff40c12SJohn Marino 
1773ff40c12SJohn Marino 
wpa_trace_bfd_addr(void * pc)1783ff40c12SJohn Marino static void wpa_trace_bfd_addr(void *pc)
1793ff40c12SJohn Marino {
1803ff40c12SJohn Marino 	bfd *abfd = cached_abfd;
1813ff40c12SJohn Marino 	struct bfd_data data;
1823ff40c12SJohn Marino 	const char *name;
1833ff40c12SJohn Marino 	char *aname = NULL;
1843ff40c12SJohn Marino 	const char *filename;
1853ff40c12SJohn Marino 
1863ff40c12SJohn Marino 	if (abfd == NULL)
1873ff40c12SJohn Marino 		return;
1883ff40c12SJohn Marino 
189*a1157835SDaniel Fojt 	data.pc = (bfd_hostptr_t) ((u8 *) pc - start_offset);
1903ff40c12SJohn Marino 	data.found = FALSE;
1913ff40c12SJohn Marino 	bfd_map_over_sections(abfd, find_addr_sect, &data);
1923ff40c12SJohn Marino 
1933ff40c12SJohn Marino 	if (!data.found)
1943ff40c12SJohn Marino 		return;
1953ff40c12SJohn Marino 
1963ff40c12SJohn Marino 	do {
1973ff40c12SJohn Marino 		if (data.function)
1983ff40c12SJohn Marino 			aname = bfd_demangle(abfd, data.function,
1993ff40c12SJohn Marino 					     DMGL_ANSI | DMGL_PARAMS);
2003ff40c12SJohn Marino 		name = aname ? aname : data.function;
2013ff40c12SJohn Marino 		filename = data.filename;
2023ff40c12SJohn Marino 		if (filename) {
2033ff40c12SJohn Marino 			char *end = os_strrchr(filename, '/');
2043ff40c12SJohn Marino 			int i = 0;
2053ff40c12SJohn Marino 			while (*filename && *filename == prg_fname[i] &&
2063ff40c12SJohn Marino 			       filename <= end) {
2073ff40c12SJohn Marino 				filename++;
2083ff40c12SJohn Marino 				i++;
2093ff40c12SJohn Marino 			}
2103ff40c12SJohn Marino 		}
2113ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "     %s() %s:%u",
2123ff40c12SJohn Marino 			   name, filename, data.line);
2133ff40c12SJohn Marino 		free(aname);
214*a1157835SDaniel Fojt 		aname = NULL;
2153ff40c12SJohn Marino 
2163ff40c12SJohn Marino 		data.found = bfd_find_inliner_info(abfd, &data.filename,
2173ff40c12SJohn Marino 						   &data.function, &data.line);
2183ff40c12SJohn Marino 	} while (data.found);
2193ff40c12SJohn Marino }
2203ff40c12SJohn Marino 
2213ff40c12SJohn Marino 
wpa_trace_bfd_addr2func(void * pc)2223ff40c12SJohn Marino static const char * wpa_trace_bfd_addr2func(void *pc)
2233ff40c12SJohn Marino {
2243ff40c12SJohn Marino 	bfd *abfd = cached_abfd;
2253ff40c12SJohn Marino 	struct bfd_data data;
2263ff40c12SJohn Marino 
2273ff40c12SJohn Marino 	if (abfd == NULL)
2283ff40c12SJohn Marino 		return NULL;
2293ff40c12SJohn Marino 
230*a1157835SDaniel Fojt 	data.pc = (bfd_hostptr_t) ((u8 *) pc - start_offset);
2313ff40c12SJohn Marino 	data.found = FALSE;
2323ff40c12SJohn Marino 	bfd_map_over_sections(abfd, find_addr_sect, &data);
2333ff40c12SJohn Marino 
2343ff40c12SJohn Marino 	if (!data.found)
2353ff40c12SJohn Marino 		return NULL;
2363ff40c12SJohn Marino 
2373ff40c12SJohn Marino 	return data.function;
2383ff40c12SJohn Marino }
2393ff40c12SJohn Marino 
2403ff40c12SJohn Marino 
wpa_trace_bfd_init(void)2413ff40c12SJohn Marino static void wpa_trace_bfd_init(void)
2423ff40c12SJohn Marino {
2433ff40c12SJohn Marino 	if (!prg_fname) {
2443ff40c12SJohn Marino 		get_prg_fname();
2453ff40c12SJohn Marino 		if (!prg_fname)
2463ff40c12SJohn Marino 			return;
2473ff40c12SJohn Marino 	}
2483ff40c12SJohn Marino 
2493ff40c12SJohn Marino 	if (!cached_abfd) {
2503ff40c12SJohn Marino 		cached_abfd = open_bfd(prg_fname);
2513ff40c12SJohn Marino 		if (!cached_abfd) {
2523ff40c12SJohn Marino 			wpa_printf(MSG_INFO, "Failed to open bfd");
2533ff40c12SJohn Marino 			return;
2543ff40c12SJohn Marino 		}
2553ff40c12SJohn Marino 	}
2563ff40c12SJohn Marino 
2573ff40c12SJohn Marino 	read_syms(cached_abfd);
2583ff40c12SJohn Marino 	if (!syms) {
2593ff40c12SJohn Marino 		wpa_printf(MSG_INFO, "Failed to read symbols");
2603ff40c12SJohn Marino 		return;
2613ff40c12SJohn Marino 	}
262*a1157835SDaniel Fojt 
263*a1157835SDaniel Fojt 	if (!start_offset_looked_up) {
264*a1157835SDaniel Fojt 		dl_iterate_phdr(callback, NULL);
265*a1157835SDaniel Fojt 		start_offset_looked_up = 1;
266*a1157835SDaniel Fojt 	}
2673ff40c12SJohn Marino }
2683ff40c12SJohn Marino 
2693ff40c12SJohn Marino 
wpa_trace_dump_funcname(const char * title,void * pc)2703ff40c12SJohn Marino void wpa_trace_dump_funcname(const char *title, void *pc)
2713ff40c12SJohn Marino {
2723ff40c12SJohn Marino 	wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc);
2733ff40c12SJohn Marino 	wpa_trace_bfd_init();
2743ff40c12SJohn Marino 	wpa_trace_bfd_addr(pc);
2753ff40c12SJohn Marino }
2763ff40c12SJohn Marino 
277*a1157835SDaniel Fojt 
wpa_trace_calling_func(const char * buf[],size_t len)278*a1157835SDaniel Fojt size_t wpa_trace_calling_func(const char *buf[], size_t len)
279*a1157835SDaniel Fojt {
280*a1157835SDaniel Fojt 	bfd *abfd;
281*a1157835SDaniel Fojt 	void *btrace_res[WPA_TRACE_LEN];
282*a1157835SDaniel Fojt 	int i, btrace_num;
283*a1157835SDaniel Fojt 	size_t pos = 0;
284*a1157835SDaniel Fojt 
285*a1157835SDaniel Fojt 	if (len == 0)
286*a1157835SDaniel Fojt 		return 0;
287*a1157835SDaniel Fojt 	if (len > WPA_TRACE_LEN)
288*a1157835SDaniel Fojt 		len = WPA_TRACE_LEN;
289*a1157835SDaniel Fojt 
290*a1157835SDaniel Fojt 	wpa_trace_bfd_init();
291*a1157835SDaniel Fojt 	abfd = cached_abfd;
292*a1157835SDaniel Fojt 	if (!abfd)
293*a1157835SDaniel Fojt 		return 0;
294*a1157835SDaniel Fojt 
295*a1157835SDaniel Fojt 	btrace_num = backtrace(btrace_res, len);
296*a1157835SDaniel Fojt 	if (btrace_num < 1)
297*a1157835SDaniel Fojt 		return 0;
298*a1157835SDaniel Fojt 
299*a1157835SDaniel Fojt 	for (i = 0; i < btrace_num; i++) {
300*a1157835SDaniel Fojt 		struct bfd_data data;
301*a1157835SDaniel Fojt 
302*a1157835SDaniel Fojt 		data.pc = (bfd_hostptr_t) ((u8 *) btrace_res[i] - start_offset);
303*a1157835SDaniel Fojt 		data.found = FALSE;
304*a1157835SDaniel Fojt 		bfd_map_over_sections(abfd, find_addr_sect, &data);
305*a1157835SDaniel Fojt 
306*a1157835SDaniel Fojt 		while (data.found) {
307*a1157835SDaniel Fojt 			if (data.function &&
308*a1157835SDaniel Fojt 			    (pos > 0 ||
309*a1157835SDaniel Fojt 			     os_strcmp(data.function, __func__) != 0)) {
310*a1157835SDaniel Fojt 				buf[pos++] = data.function;
311*a1157835SDaniel Fojt 				if (pos == len)
312*a1157835SDaniel Fojt 					return pos;
313*a1157835SDaniel Fojt 			}
314*a1157835SDaniel Fojt 
315*a1157835SDaniel Fojt 			data.found = bfd_find_inliner_info(abfd, &data.filename,
316*a1157835SDaniel Fojt 							   &data.function,
317*a1157835SDaniel Fojt 							   &data.line);
318*a1157835SDaniel Fojt 		}
319*a1157835SDaniel Fojt 	}
320*a1157835SDaniel Fojt 
321*a1157835SDaniel Fojt 	return pos;
322*a1157835SDaniel Fojt }
323*a1157835SDaniel Fojt 
3243ff40c12SJohn Marino #else /* WPA_TRACE_BFD */
3253ff40c12SJohn Marino 
3263ff40c12SJohn Marino #define wpa_trace_bfd_init() do { } while (0)
3273ff40c12SJohn Marino #define wpa_trace_bfd_addr(pc) do { } while (0)
3283ff40c12SJohn Marino #define wpa_trace_bfd_addr2func(pc) NULL
3293ff40c12SJohn Marino 
3303ff40c12SJohn Marino #endif /* WPA_TRACE_BFD */
3313ff40c12SJohn Marino 
wpa_trace_dump_func(const char * title,void ** btrace,int btrace_num)3323ff40c12SJohn Marino void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
3333ff40c12SJohn Marino {
3343ff40c12SJohn Marino 	char **sym;
3353ff40c12SJohn Marino 	int i;
3363ff40c12SJohn Marino 	enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state;
3373ff40c12SJohn Marino 
3383ff40c12SJohn Marino 	wpa_trace_bfd_init();
3393ff40c12SJohn Marino 	wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title);
3403ff40c12SJohn Marino 	sym = backtrace_symbols(btrace, btrace_num);
3413ff40c12SJohn Marino 	state = TRACE_HEAD;
3423ff40c12SJohn Marino 	for (i = 0; i < btrace_num; i++) {
3433ff40c12SJohn Marino 		const char *func = wpa_trace_bfd_addr2func(btrace[i]);
3443ff40c12SJohn Marino 		if (state == TRACE_HEAD && func &&
3453ff40c12SJohn Marino 		    (os_strcmp(func, "wpa_trace_add_ref_func") == 0 ||
3463ff40c12SJohn Marino 		     os_strcmp(func, "wpa_trace_check_ref") == 0 ||
3473ff40c12SJohn Marino 		     os_strcmp(func, "wpa_trace_show") == 0))
3483ff40c12SJohn Marino 			continue;
3493ff40c12SJohn Marino 		if (state == TRACE_TAIL && sym && sym[i] &&
3503ff40c12SJohn Marino 		    os_strstr(sym[i], "__libc_start_main"))
3513ff40c12SJohn Marino 			break;
3523ff40c12SJohn Marino 		if (state == TRACE_HEAD)
3533ff40c12SJohn Marino 			state = TRACE_RELEVANT;
3543ff40c12SJohn Marino 		if (sym)
3553ff40c12SJohn Marino 			wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]);
3563ff40c12SJohn Marino 		else
3573ff40c12SJohn Marino 			wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]);
3583ff40c12SJohn Marino 		wpa_trace_bfd_addr(btrace[i]);
3593ff40c12SJohn Marino 		if (state == TRACE_RELEVANT && func &&
3603ff40c12SJohn Marino 		    os_strcmp(func, "main") == 0)
3613ff40c12SJohn Marino 			state = TRACE_TAIL;
3623ff40c12SJohn Marino 	}
3633ff40c12SJohn Marino 	free(sym);
3643ff40c12SJohn Marino 	wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title);
3653ff40c12SJohn Marino }
3663ff40c12SJohn Marino 
3673ff40c12SJohn Marino 
wpa_trace_show(const char * title)3683ff40c12SJohn Marino void wpa_trace_show(const char *title)
3693ff40c12SJohn Marino {
3703ff40c12SJohn Marino 	struct info {
3713ff40c12SJohn Marino 		WPA_TRACE_INFO
3723ff40c12SJohn Marino 	} info;
3733ff40c12SJohn Marino 	wpa_trace_record(&info);
3743ff40c12SJohn Marino 	wpa_trace_dump(title, &info);
3753ff40c12SJohn Marino }
3763ff40c12SJohn Marino 
3773ff40c12SJohn Marino 
wpa_trace_add_ref_func(struct wpa_trace_ref * ref,const void * addr)3783ff40c12SJohn Marino void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr)
3793ff40c12SJohn Marino {
3803ff40c12SJohn Marino 	if (addr == NULL)
3813ff40c12SJohn Marino 		return;
3823ff40c12SJohn Marino 	ref->addr = addr;
3833ff40c12SJohn Marino 	wpa_trace_record(ref);
3843ff40c12SJohn Marino 	dl_list_add(&active_references, &ref->list);
3853ff40c12SJohn Marino }
3863ff40c12SJohn Marino 
3873ff40c12SJohn Marino 
wpa_trace_check_ref(const void * addr)3883ff40c12SJohn Marino void wpa_trace_check_ref(const void *addr)
3893ff40c12SJohn Marino {
3903ff40c12SJohn Marino 	struct wpa_trace_ref *ref;
3913ff40c12SJohn Marino 	dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) {
3923ff40c12SJohn Marino 		if (addr != ref->addr)
3933ff40c12SJohn Marino 			continue;
3943ff40c12SJohn Marino 		wpa_trace_show("Freeing referenced memory");
3953ff40c12SJohn Marino 		wpa_trace_dump("Reference registration", ref);
3963ff40c12SJohn Marino 		abort();
3973ff40c12SJohn Marino 	}
3983ff40c12SJohn Marino }
3993ff40c12SJohn Marino 
400*a1157835SDaniel Fojt 
wpa_trace_deinit(void)401*a1157835SDaniel Fojt void wpa_trace_deinit(void)
402*a1157835SDaniel Fojt {
403*a1157835SDaniel Fojt #ifdef WPA_TRACE_BFD
404*a1157835SDaniel Fojt 	free(syms);
405*a1157835SDaniel Fojt 	syms = NULL;
406*a1157835SDaniel Fojt #endif /* WPA_TRACE_BFD */
407*a1157835SDaniel Fojt }
408*a1157835SDaniel Fojt 
4093ff40c12SJohn Marino #endif /* WPA_TRACE */
410