#include #include "config.h" #include "backtrace.h" #define LT_MAXMSG 300 int bt_dump(struct lt_config_shared *cfg, unsigned long flags) { unw_cursor_t cursor; unw_context_t uc; int ret = 0; unw_getcontext(&uc); if (unw_init_local(&cursor, &uc) < 0) { bt_display(cfg, "unw_init_local failed"); return -1; } bt_display(cfg, "backtrace:"); do { char text[LT_MAXMSG]; struct bt_map *map; bt_word_t rel_ip = 0, ip = 0, sp; bt_word_t sym_offset = 0; bt_word_t sym_size= 0; char *map_name = NULL; char *sym_name = NULL; struct bt_symbol *symbol = NULL; int size = sizeof(bt_word_t) * 2; int symbol_found = 0; unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); if (bt_find_map(cfg, &map, ip)) { rel_ip = ip - map->base; map_name = map->name; if (bt_find_symbol(cfg, &symbol, map, rel_ip)) { sym_name = symbol->name; sym_offset = rel_ip - symbol->start; sym_size = symbol->end - symbol->start; symbol_found = 1; } } if (symbol_found) snprintf(text, LT_MAXMSG, "\t<0x%0*zx> %s+0x%zx/0x%zx [%s]", size, rel_ip, sym_name, sym_offset, sym_size, map_name); else snprintf(text, LT_MAXMSG, "\t<0x%0*zx> [%s]", size, rel_ip, map_name); bt_display(cfg, text); ret = unw_step(&cursor); if (ret < 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); snprintf(text, LT_MAXMSG, "unw_step failed for ip=%zx\n", ip); bt_display(cfg, text); } } while (ret > 0); return ret; }