static long __stdcall exception_filter(struct _EXCEPTION_POINTERS *info) { static const struct { DWORD code; const char *string; } exception_table[] = { { EXCEPTION_ACCESS_VIOLATION, "ACCESS VIOLATION" }, { EXCEPTION_DATATYPE_MISALIGNMENT, "DATATYPE MISALIGNMENT" }, { EXCEPTION_BREAKPOINT, "BREAKPOINT" }, { EXCEPTION_SINGLE_STEP, "SINGLE STEP" }, { EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "ARRAY BOUNDS EXCEEDED" }, { EXCEPTION_FLT_DENORMAL_OPERAND, "FLOAT DENORMAL OPERAND" }, { EXCEPTION_FLT_DIVIDE_BY_ZERO, "FLOAT DIVIDE BY ZERO" }, { EXCEPTION_FLT_INEXACT_RESULT, "FLOAT INEXACT RESULT" }, { EXCEPTION_FLT_INVALID_OPERATION, "FLOAT INVALID OPERATION" }, { EXCEPTION_FLT_OVERFLOW, "FLOAT OVERFLOW" }, { EXCEPTION_FLT_STACK_CHECK, "FLOAT STACK CHECK" }, { EXCEPTION_FLT_UNDERFLOW, "FLOAT UNDERFLOW" }, { EXCEPTION_INT_DIVIDE_BY_ZERO, "INTEGER DIVIDE BY ZERO" }, { EXCEPTION_INT_OVERFLOW, "INTEGER OVERFLOW" }, { EXCEPTION_PRIV_INSTRUCTION, "PRIVILEGED INSTRUCTION" }, { EXCEPTION_IN_PAGE_ERROR, "IN PAGE ERROR" }, { EXCEPTION_ILLEGAL_INSTRUCTION, "ILLEGAL INSTRUCTION" }, { EXCEPTION_NONCONTINUABLE_EXCEPTION,"NONCONTINUABLE EXCEPTION" }, { EXCEPTION_STACK_OVERFLOW, "STACK OVERFLOW" }, { EXCEPTION_INVALID_DISPOSITION, "INVALID DISPOSITION" }, { EXCEPTION_GUARD_PAGE, "GUARD PAGE VIOLATION" }, { EXCEPTION_INVALID_HANDLE, "INVALID HANDLE" }, { 0, "UNKNOWN EXCEPTION" } }; static int already_hit = 0; int i; // if we're hitting this recursively, just exit if (already_hit) return EXCEPTION_CONTINUE_SEARCH; already_hit = 1; // flush any debugging traces that were live debugger_flush_all_traces_on_abnormal_exit(); // find our man for (i = 0; exception_table[i].code != 0; i++) if (info->ExceptionRecord->ExceptionCode == exception_table[i].code) break; // print the exception type and address fprintf(stderr, "\n-----------------------------------------------------\n"); auto diagnostics = downcast<diagnostics_win32 *>(get_instance()); fprintf(stderr, "Exception at EIP=%p%s: %s\n", info->ExceptionRecord->ExceptionAddress, diagnostics->m_symbols->symbol_for_address((FPTR)info->ExceptionRecord->ExceptionAddress), exception_table[i].string); // for access violations, print more info if (info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) fprintf(stderr, "While attempting to %s memory at %p\n", info->ExceptionRecord->ExceptionInformation[0] ? "write" : "read", (void *)info->ExceptionRecord->ExceptionInformation[1]); // print the state of the CPU fprintf(stderr, "-----------------------------------------------------\n"); #ifdef PTR64 fprintf(stderr, "RAX=%p RBX=%p RCX=%p RDX=%p\n", (void *)info->ContextRecord->Rax, (void *)info->ContextRecord->Rbx, (void *)info->ContextRecord->Rcx, (void *)info->ContextRecord->Rdx); fprintf(stderr, "RSI=%p RDI=%p RBP=%p RSP=%p\n", (void *)info->ContextRecord->Rsi, (void *)info->ContextRecord->Rdi, (void *)info->ContextRecord->Rbp, (void *)info->ContextRecord->Rsp); fprintf(stderr, " R8=%p R9=%p R10=%p R11=%p\n", (void *)info->ContextRecord->R8, (void *)info->ContextRecord->R9, (void *)info->ContextRecord->R10, (void *)info->ContextRecord->R11); fprintf(stderr, "R12=%p R13=%p R14=%p R15=%p\n", (void *)info->ContextRecord->R12, (void *)info->ContextRecord->R13, (void *)info->ContextRecord->R14, (void *)info->ContextRecord->R15); #else fprintf(stderr, "EAX=%p EBX=%p ECX=%p EDX=%p\n", (void *)info->ContextRecord->Eax, (void *)info->ContextRecord->Ebx, (void *)info->ContextRecord->Ecx, (void *)info->ContextRecord->Edx); fprintf(stderr, "ESI=%p EDI=%p EBP=%p ESP=%p\n", (void *)info->ContextRecord->Esi, (void *)info->ContextRecord->Edi, (void *)info->ContextRecord->Ebp, (void *)info->ContextRecord->Esp); #endif // reprint the actual exception address fprintf(stderr, "-----------------------------------------------------\n"); fprintf(stderr, "Stack crawl:\n"); diagnostics->print_stacktrace(info->ContextRecord, GetCurrentThread()); // flush stderr, so the data is actually written when output is being redirected fflush(stderr); // exit return EXCEPTION_CONTINUE_SEARCH; }
static LONG CALLBACK exception_filter(struct _EXCEPTION_POINTERS *info) { static const struct { DWORD code; const char *string; } exception_table[] = { { EXCEPTION_ACCESS_VIOLATION, "ACCESS VIOLATION" }, { EXCEPTION_DATATYPE_MISALIGNMENT, "DATATYPE MISALIGNMENT" }, { EXCEPTION_BREAKPOINT, "BREAKPOINT" }, { EXCEPTION_SINGLE_STEP, "SINGLE STEP" }, { EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "ARRAY BOUNDS EXCEEDED" }, { EXCEPTION_FLT_DENORMAL_OPERAND, "FLOAT DENORMAL OPERAND" }, { EXCEPTION_FLT_DIVIDE_BY_ZERO, "FLOAT DIVIDE BY ZERO" }, { EXCEPTION_FLT_INEXACT_RESULT, "FLOAT INEXACT RESULT" }, { EXCEPTION_FLT_INVALID_OPERATION, "FLOAT INVALID OPERATION" }, { EXCEPTION_FLT_OVERFLOW, "FLOAT OVERFLOW" }, { EXCEPTION_FLT_STACK_CHECK, "FLOAT STACK CHECK" }, { EXCEPTION_FLT_UNDERFLOW, "FLOAT UNDERFLOW" }, { EXCEPTION_INT_DIVIDE_BY_ZERO, "INTEGER DIVIDE BY ZERO" }, { EXCEPTION_INT_OVERFLOW, "INTEGER OVERFLOW" }, { EXCEPTION_PRIV_INSTRUCTION, "PRIVILEGED INSTRUCTION" }, { EXCEPTION_IN_PAGE_ERROR, "IN PAGE ERROR" }, { EXCEPTION_ILLEGAL_INSTRUCTION, "ILLEGAL INSTRUCTION" }, { EXCEPTION_NONCONTINUABLE_EXCEPTION,"NONCONTINUABLE EXCEPTION" }, { EXCEPTION_STACK_OVERFLOW, "STACK OVERFLOW" }, { EXCEPTION_INVALID_DISPOSITION, "INVALID DISPOSITION" }, { EXCEPTION_GUARD_PAGE, "GUARD PAGE VIOLATION" }, { EXCEPTION_INVALID_HANDLE, "INVALID HANDLE" }, { 0, "UNKNOWN EXCEPTION" } }; static int already_hit = 0; int i; // if we're hitting this recursively, just exit if (already_hit) return EXCEPTION_CONTINUE_SEARCH; already_hit = 1; // flush any debugging traces that were live debugger_flush_all_traces_on_abnormal_exit(); // find our man for (i = 0; exception_table[i].code != 0; i++) if (info->ExceptionRecord->ExceptionCode == exception_table[i].code) break; // print the exception type and address fprintf(stderr, "\n-----------------------------------------------------\n"); fprintf(stderr, "Exception at EIP=%p%s: %s\n", info->ExceptionRecord->ExceptionAddress, lookup_symbol((FPTR)info->ExceptionRecord->ExceptionAddress), exception_table[i].string); // for access violations, print more info if (info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) fprintf(stderr, "While attempting to %s memory at %p\n", info->ExceptionRecord->ExceptionInformation[0] ? "write" : "read", (void *)info->ExceptionRecord->ExceptionInformation[1]); // print the state of the CPU fprintf(stderr, "-----------------------------------------------------\n"); #ifdef PTR64 fprintf(stderr, "RAX=%p RBX=%p RCX=%p RDX=%p\n", (void *)info->ContextRecord->Rax, (void *)info->ContextRecord->Rbx, (void *)info->ContextRecord->Rcx, (void *)info->ContextRecord->Rdx); fprintf(stderr, "RSI=%p RDI=%p RBP=%p RSP=%p\n", (void *)info->ContextRecord->Rsi, (void *)info->ContextRecord->Rdi, (void *)info->ContextRecord->Rbp, (void *)info->ContextRecord->Rsp); fprintf(stderr, " R8=%p R9=%p R10=%p R11=%p\n", (void *)info->ContextRecord->R8, (void *)info->ContextRecord->R9, (void *)info->ContextRecord->R10, (void *)info->ContextRecord->R11); fprintf(stderr, "R12=%p R13=%p R14=%p R15=%p\n", (void *)info->ContextRecord->R12, (void *)info->ContextRecord->R13, (void *)info->ContextRecord->R14, (void *)info->ContextRecord->R15); #else fprintf(stderr, "EAX=%p EBX=%p ECX=%p EDX=%p\n", (void *)info->ContextRecord->Eax, (void *)info->ContextRecord->Ebx, (void *)info->ContextRecord->Ecx, (void *)info->ContextRecord->Edx); fprintf(stderr, "ESI=%p EDI=%p EBP=%p ESP=%p\n", (void *)info->ContextRecord->Esi, (void *)info->ContextRecord->Edi, (void *)info->ContextRecord->Ebp, (void *)info->ContextRecord->Esp); #endif if (image_nt_header != NULL && stack_walk_64 != NULL && sym_initialize != NULL && sym_function_table_access_64 != NULL && sym_get_module_base_64 != NULL && sym_from_addr != NULL && get_module_information != NULL) { CONTEXT context = *info->ContextRecord; STACKFRAME64 stackframe; // initialize the symbol lookup sym_initialize(GetCurrentProcess(), NULL, TRUE); // reprint the actual exception address fprintf(stderr, "-----------------------------------------------------\n"); fprintf(stderr, "Stack crawl:\n"); memset(&stackframe, 0, sizeof(stackframe)); #ifdef PTR64 stackframe.AddrPC.Offset = context.Rip; stackframe.AddrFrame.Offset = context.Rsp; stackframe.AddrStack.Offset = context.Rsp; #else stackframe.AddrPC.Offset = context.Eip; stackframe.AddrFrame.Offset = context.Ebp; stackframe.AddrStack.Offset = context.Esp; #endif stackframe.AddrPC.Mode = AddrModeFlat; stackframe.AddrFrame.Mode = AddrModeFlat; stackframe.AddrStack.Mode = AddrModeFlat; while (stack_walk_64( #ifdef PTR64 IMAGE_FILE_MACHINE_AMD64, #else IMAGE_FILE_MACHINE_I386, #endif GetCurrentProcess(), GetCurrentThread(), &stackframe, &context, NULL, sym_function_table_access_64, sym_get_module_base_64, NULL)) { fprintf(stderr, " %p: %p%s\n", (void *)stackframe.AddrFrame.Offset, (void *)stackframe.AddrPC.Offset, lookup_symbol((FPTR)stackframe.AddrPC.Offset)); } } // exit return EXCEPTION_CONTINUE_SEARCH; }