| Index: tools/CrashHandler.cpp
|
| diff --git a/tools/CrashHandler.cpp b/tools/CrashHandler.cpp
|
| index cd104a6859cc67c96ebc6de767e986128dc2f446..ffd9f3bedb08eee087abfe0c03de22163654d46a 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
|
|
|
|
|