Index: tools/CrashHandler.cpp |
diff --git a/tools/CrashHandler.cpp b/tools/CrashHandler.cpp |
index cd104a6859cc67c96ebc6de767e986128dc2f446..a82d14656854f1d804c169bd7f7ca7e367b9c8c3 100644 |
--- a/tools/CrashHandler.cpp |
+++ b/tools/CrashHandler.cpp |
@@ -2,9 +2,7 @@ |
#include "SkTypes.h" |
-#include <stdio.h> |
#include <stdlib.h> |
-#include <signal.h> |
#if defined(SK_BUILD_FOR_MAC) |
@@ -20,7 +18,7 @@ static void handler(int sig) { |
unw_cursor_t cursor; |
unw_init_local(&cursor, &context); |
- fprintf(stderr, "\nSignal %d:\n", sig); |
+ SkDebugf("\nSignal %d:\n", sig); |
while (unw_step(&cursor) > 0) { |
static const size_t kMax = 256; |
char mangled[kMax], demangled[kMax]; |
@@ -31,12 +29,12 @@ static void handler(int sig) { |
size_t len = kMax; |
abi::__cxa_demangle(mangled, demangled, &len, &ok); |
- fprintf(stderr, "%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset); |
+ SkDebugf("%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset); |
} |
- fprintf(stderr, "\n"); |
+ SkDebugf("\n"); |
// Exit NOW. Don't notify other threads, don't call anything registered with atexit(). |
- _Exit(sig); |
+ _exit(sig); |
} |
#elif defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_NACL) // NACL doesn't have backtrace(). |
@@ -50,16 +48,17 @@ static void handler(int sig) { |
void* stack[kMax]; |
const int count = backtrace(stack, kMax); |
- fprintf(stderr, "\nSignal %d:\n", sig); |
+ SkDebugf("\nSignal %d:\n", sig); |
backtrace_symbols_fd(stack, count, 2/*stderr*/); |
// Exit NOW. Don't notify other threads, don't call anything registered with atexit(). |
- _Exit(sig); |
+ _exit(sig); |
} |
#endif |
#if defined(SK_BUILD_FOR_MAC) || (defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_NACL)) |
+#include <signal.h> |
void SetupCrashHandler() { |
static const int kSignals[] = { |
@@ -79,7 +78,77 @@ void SetupCrashHandler() { |
} |
} |
-// TODO: #elif defined(SK_BUILD_FOR_WIN) when I find a Windows machine to work from. |
+#elif defined(SK_BUILD_FOR_WIN) |
+ |
+#include <DbgHelp.h> |
+ |
+static const struct { |
+ const char* name; |
+ int code; |
+} kExceptions[] = { |
+#define _(E) {#E, E} |
+ _(EXCEPTION_ACCESS_VIOLATION), |
+ _(EXCEPTION_BREAKPOINT), |
+ _(EXCEPTION_INT_DIVIDE_BY_ZERO), |
+ _(EXCEPTION_STACK_OVERFLOW), |
+ // TODO: more? |
+#undef _ |
+}; |
+ |
+static LONG WINAPI handler(EXCEPTION_POINTERS* e) { |
+ const DWORD code = e->ExceptionRecord->ExceptionCode; |
+ SkDebugf("\nCaught exception %u", code); |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) { |
+ if (kExceptions[i].code == code) { |
+ SkDebugf(" %s", kExceptions[i].name); |
+ } |
+ } |
+ SkDebugf("\n"); |
+ |
+ CONTEXT* c = e->ContextRecord; |
+ |
+ HANDLE hProcess = GetCurrentProcess(); |
+ SymInitialize(hProcess, 0, true); |
+ STACKFRAME64 frame; |
+ sk_bzero(&frame, sizeof(frame)); |
+ |
+ frame.AddrPC.Offset = c->Eip; |
bungeman-skia
2014/06/18 22:28:28
CONTEXT is a completely different struct on x86 an
|
+ frame.AddrPC.Mode = AddrModeFlat; |
+ frame.AddrStack.Offset = c->Esp; |
+ frame.AddrStack.Mode = AddrModeFlat; |
+ frame.AddrFrame.Offset = c->Ebp; |
+ frame.AddrFrame.Mode = AddrModeFlat; |
+ |
+ while (StackWalk64(sizeof(void*) == 4 ? IMAGE_FILE_MACHINE_I386 : IMAGE_FILE_MACHINE_AMD64, |
bungeman-skia
2014/06/18 22:28:28
Because it's what we're actually after here, we sh
|
+ GetCurrentProcess(), |
+ GetCurrentThread(), |
+ &frame, |
+ c, |
+ NULL, |
+ SymFunctionTableAccess64, |
+ SymGetModuleBase64, |
+ NULL)) { |
+ DWORD64 offset; |
+ static const int kMaxNameLength = 1024; |
+ uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength]; |
+ sk_bzero(buffer, sizeof(buffer)); |
+ IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer); |
+ symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); |
+ symbol->MaxNameLength = kMaxNameLength - 1; |
+ SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol); |
+ SkDebugf("%s +%x\n", symbol->Name, offset); |
+ } |
+ |
+ // Exit NOW. Don't notify other threads, don't call anything registered with atexit(). |
+ _exit(1); |
+ |
+ // The compiler wants us to return something. This is what we'd do if we didn't _exit(). |
+ return EXCEPTION_EXECUTE_HANDLER; |
+} |
+ |
+void SetupCrashHandler() { |
+ SetUnhandledExceptionFilter(handler); |
+} |
#else |