14808757d7a8bbe8c773a312a894738e9ff701b5fborenet/* 24808757d7a8bbe8c773a312a894738e9ff701b5fborenet * Copyright 2014 Google Inc. 34808757d7a8bbe8c773a312a894738e9ff701b5fborenet * 44808757d7a8bbe8c773a312a894738e9ff701b5fborenet * Use of this source code is governed by a BSD-style license that can be 54808757d7a8bbe8c773a312a894738e9ff701b5fborenet * found in the LICENSE file. 64808757d7a8bbe8c773a312a894738e9ff701b5fborenet */ 74808757d7a8bbe8c773a312a894738e9ff701b5fborenet 830e6e2af14e84216b1c113fd7500d0822bc81daamtklein#include "CrashHandler.h" 930e6e2af14e84216b1c113fd7500d0822bc81daamtklein 1030e6e2af14e84216b1c113fd7500d0822bc81daamtklein#include "SkTypes.h" 1130e6e2af14e84216b1c113fd7500d0822bc81daamtklein 1230e6e2af14e84216b1c113fd7500d0822bc81daamtklein#include <stdlib.h> 1330e6e2af14e84216b1c113fd7500d0822bc81daamtklein 140e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein// Disable SetupCrashHandler() unless SK_CRASH_HANDLER is defined. 150e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein#ifndef SK_CRASH_HANDLER 160e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein void SetupCrashHandler() { } 170e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 18b47bba7c77782a9ee9e7d67a4b9c68050263e68amtklein#elif defined(GOOGLE3) 19b47bba7c77782a9ee9e7d67a4b9c68050263e68amtklein #include "base/process_state.h" 20b47bba7c77782a9ee9e7d67a4b9c68050263e68amtklein void SetupCrashHandler() { InstallSignalHandlers(); } 21b47bba7c77782a9ee9e7d67a4b9c68050263e68amtklein 220e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein#else 230e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 240e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #if defined(SK_BUILD_FOR_MAC) 250e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 260e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // We only use local unwinding, so we can define this to select a faster implementation. 270e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #define UNW_LOCAL_ONLY 280e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #include <libunwind.h> 290e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #include <cxxabi.h> 300e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 310e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static void handler(int sig) { 320e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein unw_context_t context; 330e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein unw_getcontext(&context); 340e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 350e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein unw_cursor_t cursor; 360e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein unw_init_local(&cursor, &context); 370e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 380e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf("\nSignal %d:\n", sig); 390e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein while (unw_step(&cursor) > 0) { 400e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static const size_t kMax = 256; 410e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein char mangled[kMax], demangled[kMax]; 420e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein unw_word_t offset; 430e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein unw_get_proc_name(&cursor, mangled, kMax, &offset); 440e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 450e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein int ok; 460e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein size_t len = kMax; 470e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein abi::__cxa_demangle(mangled, demangled, &len, &ok); 480e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 490e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf("%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset); 500e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 510e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf("\n"); 520e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 530e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // Exit NOW. Don't notify other threads, don't call anything registered with atexit(). 540e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein _Exit(sig); 550e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 560e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 574808757d7a8bbe8c773a312a894738e9ff701b5fborenet #elif defined(SK_BUILD_FOR_UNIX) 580e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 590e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // We'd use libunwind here too, but it's a pain to get installed for 600e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // both 32 and 64 bit on bots. Doesn't matter much: catchsegv is best anyway. 610e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #include <execinfo.h> 620e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 630e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static void handler(int sig) { 640e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static const int kMax = 64; 650e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein void* stack[kMax]; 660e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein const int count = backtrace(stack, kMax); 670e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 680e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf("\nSignal %d [%s]:\n", sig, strsignal(sig)); 690e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein backtrace_symbols_fd(stack, count, 2/*stderr*/); 700e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 710e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // Exit NOW. Don't notify other threads, don't call anything registered with atexit(). 720e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein _Exit(sig); 7330e6e2af14e84216b1c113fd7500d0822bc81daamtklein } 740e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 750e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #endif 760e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 774808757d7a8bbe8c773a312a894738e9ff701b5fborenet #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) 780e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #include <signal.h> 790e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 800e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein void SetupCrashHandler() { 810e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static const int kSignals[] = { 820e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SIGABRT, 830e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SIGBUS, 840e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SIGFPE, 850e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SIGILL, 860e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SIGSEGV, 870e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein }; 880e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 890e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) { 900e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // Register our signal handler unless something's already done so (e.g. catchsegv). 910e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein void (*prev)(int) = signal(kSignals[i], handler); 920e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein if (prev != SIG_DFL) { 930e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein signal(kSignals[i], prev); 940e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 950e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 963f73e8c8d589e0d5a1f75327b4aa22c1e745732dmtklein } 9730e6e2af14e84216b1c113fd7500d0822bc81daamtklein 980e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #elif defined(SK_CRASH_HANDLER) && defined(SK_BUILD_FOR_WIN) 990e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1000e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #include <DbgHelp.h> 1010e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1020e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static const struct { 1030e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein const char* name; 1040e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein int code; 1050e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } kExceptions[] = { 1060e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #define _(E) {#E, E} 1070e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein _(EXCEPTION_ACCESS_VIOLATION), 1080e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein _(EXCEPTION_BREAKPOINT), 1090e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein _(EXCEPTION_INT_DIVIDE_BY_ZERO), 1100e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein _(EXCEPTION_STACK_OVERFLOW), 1110e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // TODO: more? 1120e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #undef _ 1130e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein }; 1140e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1150e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static LONG WINAPI handler(EXCEPTION_POINTERS* e) { 1160e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein const DWORD code = e->ExceptionRecord->ExceptionCode; 1170e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf("\nCaught exception %u", code); 1180e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) { 1190e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein if (kExceptions[i].code == code) { 1200e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf(" %s", kExceptions[i].name); 1210e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 1220e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 1230e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf("\n"); 1240e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1250e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // We need to run SymInitialize before doing any of the stack walking below. 1260e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein HANDLE hProcess = GetCurrentProcess(); 1270e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SymInitialize(hProcess, 0, true); 1280e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1290e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein STACKFRAME64 frame; 1300e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein sk_bzero(&frame, sizeof(frame)); 1310e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // Start frame off from the frame that triggered the exception. 1320e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein CONTEXT* c = e->ContextRecord; 1330e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrPC.Mode = AddrModeFlat; 1340e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrStack.Mode = AddrModeFlat; 1350e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrFrame.Mode = AddrModeFlat; 1360e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #if defined(_X86_) 1370e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrPC.Offset = c->Eip; 1380e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrStack.Offset = c->Esp; 1390e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrFrame.Offset = c->Ebp; 1400e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein const DWORD machineType = IMAGE_FILE_MACHINE_I386; 1410e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #elif defined(_AMD64_) 1420e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrPC.Offset = c->Rip; 1430e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrStack.Offset = c->Rsp; 1440e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein frame.AddrFrame.Offset = c->Rbp; 1450e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein const DWORD machineType = IMAGE_FILE_MACHINE_AMD64; 1460e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #endif 1470e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1480e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein while (StackWalk64(machineType, 1490e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein GetCurrentProcess(), 1500e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein GetCurrentThread(), 1510e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein &frame, 1520e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein c, 1530e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein NULL, 1540e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SymFunctionTableAccess64, 1550e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SymGetModuleBase64, 1560e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein NULL)) { 1570e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // Buffer to store symbol name in. 1580e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein static const int kMaxNameLength = 1024; 1590e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength]; 1600e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein sk_bzero(buffer, sizeof(buffer)); 1610e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1620e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in 1630e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // how much space it can use. 1640e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer); 1650e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 1660e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein symbol->MaxNameLength = kMaxNameLength - 1; 1670e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1680e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // Translate the current PC into a symbol and byte offset from the symbol. 1690e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein DWORD64 offset; 1700e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol); 1710e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1720e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SkDebugf("%s +%x\n", symbol->Name, offset); 1730e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 1740e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1750e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // Exit NOW. Don't notify other threads, don't call anything registered with atexit(). 1760e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein _exit(1); 1770e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1780e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // The compiler wants us to return something. This is what we'd do 1790e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein // if we didn't _exit(). 1800e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein return EXCEPTION_EXECUTE_HANDLER; 1810e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 1820e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1830e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein void SetupCrashHandler() { 1840e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein SetUnhandledExceptionFilter(handler); 1850e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein } 1860e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein 1870e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #else // We asked for SK_CRASH_HANDLER, but it's not Mac, Linux, or Windows. Sorry! 18830e6e2af14e84216b1c113fd7500d0822bc81daamtklein 1890e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein void SetupCrashHandler() { } 19030e6e2af14e84216b1c113fd7500d0822bc81daamtklein 1910e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein #endif 1920e3fac215d0ee2e2efaca69b7d53f636f4fe5ba7mtklein#endif // SK_CRASH_HANDLER 193