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>
217832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt
227832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#define DMGL_PARAMS      (1 << 0)
237832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#define DMGL_ANSI        (1 << 1)
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char *prg_fname = NULL;
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic bfd *cached_abfd = NULL;
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic asymbol **syms = NULL;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void get_prg_fname(void)
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char exe[50], fname[512];
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid());
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = readlink(exe, fname, sizeof(fname) - 1);
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0 || len >= (int) sizeof(fname)) {
36fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		wpa_printf(MSG_ERROR, "readlink: %s", strerror(errno));
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fname[len] = '\0';
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prg_fname = strdup(fname);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic bfd * open_bfd(const char *fname)
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd *abfd;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **matching;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	abfd = bfd_openr(prg_fname, NULL);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (abfd == NULL) {
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "bfd_openr failed");
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bfd_check_format(abfd, bfd_archive)) {
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "bfd_check_format failed");
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bfd_close(abfd);
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "bfd_check_format_matches failed");
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free(matching);
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bfd_close(abfd);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return abfd;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void read_syms(bfd *abfd)
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	long storage, symcount;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_boolean dynamic = FALSE;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (syms)
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "No symbols");
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	storage = bfd_get_symtab_upper_bound(abfd);
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (storage == 0) {
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		storage = bfd_get_dynamic_symtab_upper_bound(abfd);
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dynamic = TRUE;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (storage < 0) {
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Unknown symtab upper bound");
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	syms = malloc(storage);
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (syms == NULL) {
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to allocate memory for symtab "
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(%ld bytes)", storage);
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dynamic)
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		symcount = bfd_canonicalize_symtab(abfd, syms);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (symcount < 0) {
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab",
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dynamic ? "dynamic " : "");
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free(syms);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		syms = NULL;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct bfd_data {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_vma pc;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_boolean found;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *filename;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *function;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int line;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void find_addr_sect(bfd *abfd, asection *section, void *obj)
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct bfd_data *data = obj;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_vma vma;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_size_type size;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->found)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(bfd_get_section_vma(abfd, section)))
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	vma = bfd_get_section_vma(abfd, section);
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->pc < vma)
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size = bfd_get_section_size(section);
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->pc >= vma + size)
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->found = bfd_find_nearest_line(abfd, section, syms,
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    data->pc - vma,
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &data->filename,
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &data->function,
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &data->line);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_trace_bfd_addr(void *pc)
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd *abfd = cached_abfd;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct bfd_data data;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *name;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *aname = NULL;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *filename;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (abfd == NULL)
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
163746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	data.pc = (bfd_hostptr_t) pc;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.found = FALSE;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_map_over_sections(abfd, find_addr_sect, &data);
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!data.found)
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data.function)
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			aname = bfd_demangle(abfd, data.function,
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     DMGL_ANSI | DMGL_PARAMS);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name = aname ? aname : data.function;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		filename = data.filename;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (filename) {
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			char *end = os_strrchr(filename, '/');
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int i = 0;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			while (*filename && *filename == prg_fname[i] &&
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       filename <= end) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				filename++;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				i++;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "     %s() %s:%u",
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   name, filename, data.line);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free(aname);
1887d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt		aname = NULL;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data.found = bfd_find_inliner_info(abfd, &data.filename,
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   &data.function, &data.line);
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (data.found);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * wpa_trace_bfd_addr2func(void *pc)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd *abfd = cached_abfd;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct bfd_data data;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (abfd == NULL)
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
204746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	data.pc = (bfd_hostptr_t) pc;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.found = FALSE;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bfd_map_over_sections(abfd, find_addr_sect, &data);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!data.found)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data.function;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_trace_bfd_init(void)
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!prg_fname) {
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		get_prg_fname();
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!prg_fname)
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!cached_abfd) {
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cached_abfd = open_bfd(prg_fname);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!cached_abfd) {
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "Failed to open bfd");
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	read_syms(cached_abfd);
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!syms) {
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to read symbols");
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_dump_funcname(const char *title, void *pc)
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc);
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_bfd_init();
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_bfd_addr(pc);
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
246746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
247746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidtsize_t wpa_trace_calling_func(const char *buf[], size_t len)
248746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt{
249746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	bfd *abfd;
250746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	void *btrace_res[WPA_TRACE_LEN];
251746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	int i, btrace_num;
252746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	size_t pos = 0;
253746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
254746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	if (len == 0)
255746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		return 0;
256746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	if (len > WPA_TRACE_LEN)
257746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		len = WPA_TRACE_LEN;
258746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
259746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	wpa_trace_bfd_init();
260746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	abfd = cached_abfd;
261746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	if (!abfd)
262746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		return 0;
263746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
264746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	btrace_num = backtrace(btrace_res, len);
265746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	if (btrace_num < 1)
266746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		return 0;
267746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
268746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	for (i = 0; i < btrace_num; i++) {
269746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		struct bfd_data data;
270746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
271746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		data.pc = (bfd_hostptr_t) btrace_res[i];
272746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		data.found = FALSE;
273746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		bfd_map_over_sections(abfd, find_addr_sect, &data);
274746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
275746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		while (data.found) {
276746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt			if (data.function &&
277746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt			    (pos > 0 ||
278746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt			     os_strcmp(data.function, __func__) != 0)) {
279746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt				buf[pos++] = data.function;
280746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt				if (pos == len)
281746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt					return pos;
282746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt			}
283746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
284746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt			data.found = bfd_find_inliner_info(abfd, &data.filename,
285746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt							   &data.function,
286746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt							   &data.line);
287746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt		}
288746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	}
289746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
290746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	return pos;
291746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt}
292746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE_BFD */
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_trace_bfd_init() do { } while (0)
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_trace_bfd_addr(pc) do { } while (0)
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define wpa_trace_bfd_addr2func(pc) NULL
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE_BFD */
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **sym;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_bfd_init();
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sym = backtrace_symbols(btrace, btrace_num);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	state = TRACE_HEAD;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < btrace_num; i++) {
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *func = wpa_trace_bfd_addr2func(btrace[i]);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_HEAD && func &&
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (os_strcmp(func, "wpa_trace_add_ref_func") == 0 ||
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     os_strcmp(func, "wpa_trace_check_ref") == 0 ||
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     os_strcmp(func, "wpa_trace_show") == 0))
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_TAIL && sym && sym[i] &&
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strstr(sym[i], "__libc_start_main"))
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_HEAD)
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			state = TRACE_RELEVANT;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sym)
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_bfd_addr(btrace[i]);
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state == TRACE_RELEVANT && func &&
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strcmp(func, "main") == 0)
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			state = TRACE_TAIL;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	free(sym);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title);
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_show(const char *title)
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct info {
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_TRACE_INFO
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} info;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_record(&info);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_dump(title, &info);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr)
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr == NULL)
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ref->addr = addr;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_record(ref);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&active_references, &ref->list);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_trace_check_ref(const void *addr)
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_trace_ref *ref;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) {
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (addr != ref->addr)
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_show("Freeing referenced memory");
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_dump("Reference registration", ref);
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		abort();
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
36957c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
37057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtvoid wpa_trace_deinit(void)
37157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt{
3729c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt#ifdef WPA_TRACE_BFD
37357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	free(syms);
37457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	syms = NULL;
3759c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt#endif /* WPA_TRACE_BFD */
37657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt}
37757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
379