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