// return location at which the exception <er> occurred. // params: see debug_ResolveSymbol. static void GetExceptionLocus(EXCEPTION_POINTERS* ep, wchar_t* file, int* line, wchar_t* func) { // HACK: <ep> provides no useful information - ExceptionAddress always // points to kernel32!RaiseException. we use debug_GetCaller to // determine the real location. const wchar_t* const lastFuncToSkip = L"RaiseException"; void* func_addr = debug_GetCaller(ep->ContextRecord, lastFuncToSkip); (void)debug_ResolveSymbol(func_addr, func, file, line); }
Status debug_DumpStack(wchar_t* buf, size_t max_chars, void* UNUSED(context), const wchar_t* UNUSED(lastFuncToSkip)) { static const size_t N_FRAMES = 16; void *bt[N_FRAMES]; int bt_size = 0; wchar_t *bufpos = buf; wchar_t *bufend = buf + max_chars; bt_size = backtrace(bt, ARRAY_SIZE(bt)); // Assumed max length of a single print-out static const size_t MAX_OUT_CHARS = 1024; for (size_t i = 0; (int)i < bt_size && bufpos+MAX_OUT_CHARS < bufend; i++) { wchar_t file[DEBUG_FILE_CHARS]; wchar_t symbol[DEBUG_SYMBOL_CHARS]; int line; int len; if (debug_ResolveSymbol(bt[i], symbol, file, &line) == 0) { if (file[0]) len = swprintf(bufpos, MAX_OUT_CHARS, L"(%p) %ls:%d %ls\n", bt[i], file, line, symbol); else len = swprintf(bufpos, MAX_OUT_CHARS, L"(%p) %ls\n", bt[i], symbol); } else { len = swprintf(bufpos, MAX_OUT_CHARS, L"(%p)\n", bt[i]); } if (len < 0) { // MAX_OUT_CHARS exceeded, realistically this was caused by some // mindbogglingly long symbol name... replace the end with an // ellipsis and a newline memcpy(&bufpos[MAX_OUT_CHARS-6], L"...\n", 5*sizeof(wchar_t)); len = MAX_OUT_CHARS; } bufpos += len; } return INFO::OK; }