void StackAnalyzer::get_symbols(std::function<void (const backtrace_symbol *)> cb, bool reversed) const { info_cb_data_t info_cb_data; for (void *pc : this->stack_addrs) { info_cb_data.pc = reinterpret_cast<uintptr_t>(pc); // note: a call to backtrace_pcinfo may, in semi-rare cases, push back // multiple symbols to result. That's nothing to worry about, though. // If you decide you don't like it, make pcinfo_callback return 1. backtrace_pcinfo( bt_state, info_cb_data.pc, backtrace_pcinfo_callback, backtrace_pcinfo_error_callback, reinterpret_cast<void *>(&info_cb_data) ); } if (reversed) { // this entire vector thing would only be needed for reversed=true... for (size_t idx = info_cb_data.symbols.size(); idx-- > 0;) { cb(&info_cb_data.symbols[idx]); } } else { for (backtrace_symbol &symbol : info_cb_data.symbols) { cb(&symbol); } } }
static _Unwind_Reason_Code unwind (struct _Unwind_Context *context, void *vdata) { struct backtrace_data *bdata = (struct backtrace_data *) vdata; uintptr_t pc; int ip_before_insn = 0; #ifdef HAVE_GETIPINFO pc = _Unwind_GetIPInfo (context, &ip_before_insn); #else pc = _Unwind_GetIP (context); #endif if (bdata->skip > 0) { --bdata->skip; return _URC_NO_REASON; } if (!ip_before_insn) --pc; if (!bdata->can_alloc) bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL); else bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, bdata->error_callback, bdata->data); if (bdata->ret != 0) return _URC_END_OF_STACK; return _URC_NO_REASON; }