18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Backtrace debugging
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "trace.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct dl_list active_references =
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ &active_references, &active_references };
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE_BFD
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <bfd.h>
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __linux__
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <demangle.h>
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* __linux__ */
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <libiberty/demangle.h>
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __linux__ */
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char *prg_fname = NULL;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic bfd *cached_abfd = NULL;
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic asymbol **syms = NULL;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void get_prg_fname(void)
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char exe[50], fname[512];
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid());
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = readlink(exe, fname, sizeof(fname) - 1);
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0 || len >= (int) sizeof(fname)) {
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("readlink");
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fname[len] = '\0';
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prg_fname = strdup(fname);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic bfd * open_bfd(const char *fname)
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd *abfd;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **matching;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	abfd = bfd_openr(prg_fname, NULL);
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (abfd == NULL) {
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "bfd_openr failed");
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bfd_check_format(abfd, bfd_archive)) {
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "bfd_check_format failed");
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bfd_close(abfd);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "bfd_check_format_matches failed");
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free(matching);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bfd_close(abfd);
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return abfd;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void read_syms(bfd *abfd)
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	long storage, symcount;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_boolean dynamic = FALSE;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (syms)
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) {
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "No symbols");
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	storage = bfd_get_symtab_upper_bound(abfd);
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (storage == 0) {
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		storage = bfd_get_dynamic_symtab_upper_bound(abfd);
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dynamic = TRUE;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (storage < 0) {
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Unknown symtab upper bound");
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	syms = malloc(storage);
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (syms == NULL) {
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to allocate memory for symtab "
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(%ld bytes)", storage);
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dynamic)
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		symcount = bfd_canonicalize_symtab(abfd, syms);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (symcount < 0) {
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab",
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dynamic ? "dynamic " : "");
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free(syms);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		syms = NULL;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct bfd_data {
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_vma pc;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_boolean found;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *filename;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *function;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int line;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void find_addr_sect(bfd *abfd, asection *section, void *obj)
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct bfd_data *data = obj;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_vma vma;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_size_type size;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->found)
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(bfd_get_section_vma(abfd, section)))
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	vma = bfd_get_section_vma(abfd, section);
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->pc < vma)
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size = bfd_get_section_size(section);
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->pc >= vma + size)
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->found = bfd_find_nearest_line(abfd, section, syms,
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    data->pc - vma,
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &data->filename,
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &data->function,
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &data->line);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_trace_bfd_addr(void *pc)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd *abfd = cached_abfd;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct bfd_data data;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *name;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *aname = NULL;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *filename;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (abfd == NULL)
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.pc = (bfd_vma) pc;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.found = FALSE;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_map_over_sections(abfd, find_addr_sect, &data);
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!data.found)
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data.function)
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			aname = bfd_demangle(abfd, data.function,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     DMGL_ANSI | DMGL_PARAMS);
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name = aname ? aname : data.function;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		filename = data.filename;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (filename) {
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			char *end = os_strrchr(filename, '/');
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int i = 0;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			while (*filename && *filename == prg_fname[i] &&
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       filename <= end) {
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				filename++;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				i++;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "     %s() %s:%u",
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   name, filename, data.line);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free(aname);
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data.found = bfd_find_inliner_info(abfd, &data.filename,
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   &data.function, &data.line);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (data.found);
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * wpa_trace_bfd_addr2func(void *pc)
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd *abfd = cached_abfd;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct bfd_data data;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (abfd == NULL)
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.pc = (bfd_vma) pc;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.found = FALSE;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_map_over_sections(abfd, find_addr_sect, &data);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!data.found)
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data.function;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_trace_bfd_init(void)
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!prg_fname) {
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		get_prg_fname();
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!prg_fname)
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!cached_abfd) {
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cached_abfd = open_bfd(prg_fname);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!cached_abfd) {
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "Failed to open bfd");
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	read_syms(cached_abfd);
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!syms) {
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to read symbols");
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_dump_funcname(const char *title, void *pc)
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_bfd_init();
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_bfd_addr(pc);
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE_BFD */
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_trace_bfd_init() do { } while (0)
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_trace_bfd_addr(pc) do { } while (0)
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_trace_bfd_addr2func(pc) NULL
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE_BFD */
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **sym;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_bfd_init();
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title);
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sym = backtrace_symbols(btrace, btrace_num);
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = TRACE_HEAD;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < btrace_num; i++) {
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *func = wpa_trace_bfd_addr2func(btrace[i]);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_HEAD && func &&
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (os_strcmp(func, "wpa_trace_add_ref_func") == 0 ||
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     os_strcmp(func, "wpa_trace_check_ref") == 0 ||
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     os_strcmp(func, "wpa_trace_show") == 0))
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_TAIL && sym && sym[i] &&
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strstr(sym[i], "__libc_start_main"))
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_HEAD)
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			state = TRACE_RELEVANT;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sym)
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]);
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_bfd_addr(btrace[i]);
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_RELEVANT && func &&
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strcmp(func, "main") == 0)
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			state = TRACE_TAIL;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	free(sym);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_show(const char *title)
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct info {
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_TRACE_INFO
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} info;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_record(&info);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_dump(title, &info);
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr)
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr == NULL)
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ref->addr = addr;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_record(ref);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&active_references, &ref->list);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_check_ref(const void *addr)
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_trace_ref *ref;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) {
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (addr != ref->addr)
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_show("Freeing referenced memory");
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_dump("Reference registration", ref);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		abort();
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
324