aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2014-06-19 07:41:58 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-06-19 07:41:59 -0700
commit3f73e8c8d589e0d5a1f75327b4aa22c1e745732d (patch)
tree0b7a8e78028cffe7048ba9dfc19addccb50c89e8 /tools
parent373dd9b52f88158edd1e24419e6d937efaf59d55 (diff)
CrashHandler for Windows.
Plus, print out assertion failures on Windows, and some little tweaks to CrashHandler on other platforms for consistency. BUG=skia: R=bungeman@google.com, mtklein@google.com, reed@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/340523007
Diffstat (limited to 'tools')
-rw-r--r--tools/CrashHandler.cpp98
1 files changed, 91 insertions, 7 deletions
diff --git a/tools/CrashHandler.cpp b/tools/CrashHandler.cpp
index cd104a6859..ffd9f3bedb 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,9 +29,9 @@ 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);
@@ -50,7 +48,7 @@ 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().
@@ -60,6 +58,7 @@ static void handler(int 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,92 @@ 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");
+
+ // We need to run SymInitialize before doing any of the stack walking below.
+ HANDLE hProcess = GetCurrentProcess();
+ SymInitialize(hProcess, 0, true);
+
+ STACKFRAME64 frame;
+ sk_bzero(&frame, sizeof(frame));
+ // Start frame off from the frame that triggered the exception.
+ CONTEXT* c = e->ContextRecord;
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrStack.Mode = AddrModeFlat;
+ frame.AddrFrame.Mode = AddrModeFlat;
+#if defined(_X86_)
+ frame.AddrPC.Offset = c->Eip;
+ frame.AddrStack.Offset = c->Esp;
+ frame.AddrFrame.Offset = c->Ebp;
+ const DWORD machineType = IMAGE_FILE_MACHINE_I386;
+#elif defined(_AMD64_)
+ frame.AddrPC.Offset = c->Rip;
+ frame.AddrStack.Offset = c->Rsp;
+ frame.AddrFrame.Offset = c->Rbp;
+ const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
+#endif
+
+ while (StackWalk64(machineType,
+ GetCurrentProcess(),
+ GetCurrentThread(),
+ &frame,
+ c,
+ NULL,
+ SymFunctionTableAccess64,
+ SymGetModuleBase64,
+ NULL)) {
+ // Buffer to store symbol name in.
+ static const int kMaxNameLength = 1024;
+ uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength];
+ sk_bzero(buffer, sizeof(buffer));
+
+ // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in how much space it can use.
+ IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer);
+ symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+ symbol->MaxNameLength = kMaxNameLength - 1;
+
+ // Translate the current PC into a symbol and byte offset from the symbol.
+ DWORD64 offset;
+ 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