Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(838)

Side by Side Diff: tools/CrashHandler.cpp

Issue 364033002: Gate CrashHandler with SK_CRASH_HANDLER. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/CrashHandler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #include "CrashHandler.h" 1 #include "CrashHandler.h"
2 2
3 #include "SkTypes.h" 3 #include "SkTypes.h"
4 4
5 #include <stdlib.h> 5 #include <stdlib.h>
6 6
7 #if defined(SK_BUILD_FOR_MAC) 7 // Disable SetupCrashHandler() unless SK_CRASH_HANDLER is defined.
8 8 #ifndef SK_CRASH_HANDLER
9 // We only use local unwinding, so we can define this to select a faster impleme ntation. 9 void SetupCrashHandler() { }
10 #define UNW_LOCAL_ONLY
11 #include <libunwind.h>
12 #include <cxxabi.h>
13
14 static void handler(int sig) {
15 unw_context_t context;
16 unw_getcontext(&context);
17
18 unw_cursor_t cursor;
19 unw_init_local(&cursor, &context);
20
21 SkDebugf("\nSignal %d:\n", sig);
22 while (unw_step(&cursor) > 0) {
23 static const size_t kMax = 256;
24 char mangled[kMax], demangled[kMax];
25 unw_word_t offset;
26 unw_get_proc_name(&cursor, mangled, kMax, &offset);
27
28 int ok;
29 size_t len = kMax;
30 abi::__cxa_demangle(mangled, demangled, &len, &ok);
31
32 SkDebugf("%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset) ;
33 }
34 SkDebugf("\n");
35
36 // Exit NOW. Don't notify other threads, don't call anything registered wit h atexit().
37 _Exit(sig);
38 }
39
40 #elif defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_NACL) // NACL doesn' t have backtrace().
41
42 // We'd use libunwind here too, but it's a pain to get installed for both 32 and 64 bit on bots.
43 // Doesn't matter much: catchsegv is best anyway.
44 #include <execinfo.h>
45
46 static void handler(int sig) {
47 static const int kMax = 64;
48 void* stack[kMax];
49 const int count = backtrace(stack, kMax);
50
51 SkDebugf("\nSignal %d [%s]:\n", sig, strsignal(sig));
52 backtrace_symbols_fd(stack, count, 2/*stderr*/);
53
54 // Exit NOW. Don't notify other threads, don't call anything registered wit h atexit().
55 _Exit(sig);
56 }
57
58 #endif
59
60 #if defined(SK_BUILD_FOR_MAC) || (defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUIL D_FOR_NACL))
61 #include <signal.h>
62
63 void SetupCrashHandler() {
64 static const int kSignals[] = {
65 SIGABRT,
66 SIGBUS,
67 SIGFPE,
68 SIGILL,
69 SIGSEGV,
70 };
71
72 for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) {
73 // Register our signal handler unless something's already done so (e.g. catchsegv).
74 void (*prev)(int) = signal(kSignals[i], handler);
75 if (prev != SIG_DFL) {
76 signal(kSignals[i], prev);
77 }
78 }
79 }
80
81 #elif defined(SK_BUILD_FOR_WIN)
82
83 #include <DbgHelp.h>
84
85 static const struct {
86 const char* name;
87 int code;
88 } kExceptions[] = {
89 #define _(E) {#E, E}
90 _(EXCEPTION_ACCESS_VIOLATION),
91 _(EXCEPTION_BREAKPOINT),
92 _(EXCEPTION_INT_DIVIDE_BY_ZERO),
93 _(EXCEPTION_STACK_OVERFLOW),
94 // TODO: more?
95 #undef _
96 };
97
98 static LONG WINAPI handler(EXCEPTION_POINTERS* e) {
99 const DWORD code = e->ExceptionRecord->ExceptionCode;
100 SkDebugf("\nCaught exception %u", code);
101 for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) {
102 if (kExceptions[i].code == code) {
103 SkDebugf(" %s", kExceptions[i].name);
104 }
105 }
106 SkDebugf("\n");
107
108 // We need to run SymInitialize before doing any of the stack walking below.
109 HANDLE hProcess = GetCurrentProcess();
110 SymInitialize(hProcess, 0, true);
111
112 STACKFRAME64 frame;
113 sk_bzero(&frame, sizeof(frame));
114 // Start frame off from the frame that triggered the exception.
115 CONTEXT* c = e->ContextRecord;
116 frame.AddrPC.Mode = AddrModeFlat;
117 frame.AddrStack.Mode = AddrModeFlat;
118 frame.AddrFrame.Mode = AddrModeFlat;
119 #if defined(_X86_)
120 frame.AddrPC.Offset = c->Eip;
121 frame.AddrStack.Offset = c->Esp;
122 frame.AddrFrame.Offset = c->Ebp;
123 const DWORD machineType = IMAGE_FILE_MACHINE_I386;
124 #elif defined(_AMD64_)
125 frame.AddrPC.Offset = c->Rip;
126 frame.AddrStack.Offset = c->Rsp;
127 frame.AddrFrame.Offset = c->Rbp;
128 const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
129 #endif
130
131 while (StackWalk64(machineType,
132 GetCurrentProcess(),
133 GetCurrentThread(),
134 &frame,
135 c,
136 NULL,
137 SymFunctionTableAccess64,
138 SymGetModuleBase64,
139 NULL)) {
140 // Buffer to store symbol name in.
141 static const int kMaxNameLength = 1024;
142 uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength];
143 sk_bzero(buffer, sizeof(buffer));
144
145 // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in how much space it can use.
146 IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer );
147 symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
148 symbol->MaxNameLength = kMaxNameLength - 1;
149
150 // Translate the current PC into a symbol and byte offset from the symbo l.
151 DWORD64 offset;
152 SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol);
153
154 SkDebugf("%s +%x\n", symbol->Name, offset);
155 }
156
157 // Exit NOW. Don't notify other threads, don't call anything registered wit h atexit().
158 _exit(1);
159
160 // The compiler wants us to return something. This is what we'd do if we di dn't _exit().
161 return EXCEPTION_EXECUTE_HANDLER;
162 }
163
164 void SetupCrashHandler() {
165 SetUnhandledExceptionFilter(handler);
166 }
167 10
168 #else 11 #else
169 12
170 void SetupCrashHandler() { } 13 #if defined(SK_BUILD_FOR_MAC)
171 14
172 #endif 15 // We only use local unwinding, so we can define this to select a faster implementation.
16 #define UNW_LOCAL_ONLY
17 #include <libunwind.h>
18 #include <cxxabi.h>
19
20 static void handler(int sig) {
21 unw_context_t context;
22 unw_getcontext(&context);
23
24 unw_cursor_t cursor;
25 unw_init_local(&cursor, &context);
26
27 SkDebugf("\nSignal %d:\n", sig);
28 while (unw_step(&cursor) > 0) {
29 static const size_t kMax = 256;
30 char mangled[kMax], demangled[kMax];
31 unw_word_t offset;
32 unw_get_proc_name(&cursor, mangled, kMax, &offset);
33
34 int ok;
35 size_t len = kMax;
36 abi::__cxa_demangle(mangled, demangled, &len, &ok);
37
38 SkDebugf("%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t )offset);
39 }
40 SkDebugf("\n");
41
42 // Exit NOW. Don't notify other threads, don't call anything regist ered with atexit().
43 _Exit(sig);
44 }
45
46 #elif defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_NACL) // NACL doe sn't have backtrace.
47
48 // We'd use libunwind here too, but it's a pain to get installed for
49 // both 32 and 64 bit on bots. Doesn't matter much: catchsegv is best a nyway.
50 #include <execinfo.h>
51
52 static void handler(int sig) {
53 static const int kMax = 64;
54 void* stack[kMax];
55 const int count = backtrace(stack, kMax);
56
57 SkDebugf("\nSignal %d [%s]:\n", sig, strsignal(sig));
58 backtrace_symbols_fd(stack, count, 2/*stderr*/);
59
60 // Exit NOW. Don't notify other threads, don't call anything regist ered with atexit().
61 _Exit(sig);
62 }
63
64 #endif
65
66 #if (defined(SK_BUILD_FOR_MAC) || (defined(SK_BUILD_FOR_UNIX) && !defined(SK _BUILD_FOR_NACL)))
67 #include <signal.h>
68
69 void SetupCrashHandler() {
70 static const int kSignals[] = {
71 SIGABRT,
72 SIGBUS,
73 SIGFPE,
74 SIGILL,
75 SIGSEGV,
76 };
77
78 for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) {
79 // Register our signal handler unless something's already done s o (e.g. catchsegv).
80 void (*prev)(int) = signal(kSignals[i], handler);
81 if (prev != SIG_DFL) {
82 signal(kSignals[i], prev);
83 }
84 }
85 }
86
87 #elif defined(SK_CRASH_HANDLER) && defined(SK_BUILD_FOR_WIN)
88
89 #include <DbgHelp.h>
90
91 static const struct {
92 const char* name;
93 int code;
94 } kExceptions[] = {
95 #define _(E) {#E, E}
96 _(EXCEPTION_ACCESS_VIOLATION),
97 _(EXCEPTION_BREAKPOINT),
98 _(EXCEPTION_INT_DIVIDE_BY_ZERO),
99 _(EXCEPTION_STACK_OVERFLOW),
100 // TODO: more?
101 #undef _
102 };
103
104 static LONG WINAPI handler(EXCEPTION_POINTERS* e) {
105 const DWORD code = e->ExceptionRecord->ExceptionCode;
106 SkDebugf("\nCaught exception %u", code);
107 for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) {
108 if (kExceptions[i].code == code) {
109 SkDebugf(" %s", kExceptions[i].name);
110 }
111 }
112 SkDebugf("\n");
113
114 // We need to run SymInitialize before doing any of the stack walkin g below.
115 HANDLE hProcess = GetCurrentProcess();
116 SymInitialize(hProcess, 0, true);
117
118 STACKFRAME64 frame;
119 sk_bzero(&frame, sizeof(frame));
120 // Start frame off from the frame that triggered the exception.
121 CONTEXT* c = e->ContextRecord;
122 frame.AddrPC.Mode = AddrModeFlat;
123 frame.AddrStack.Mode = AddrModeFlat;
124 frame.AddrFrame.Mode = AddrModeFlat;
125 #if defined(_X86_)
126 frame.AddrPC.Offset = c->Eip;
127 frame.AddrStack.Offset = c->Esp;
128 frame.AddrFrame.Offset = c->Ebp;
129 const DWORD machineType = IMAGE_FILE_MACHINE_I386;
130 #elif defined(_AMD64_)
131 frame.AddrPC.Offset = c->Rip;
132 frame.AddrStack.Offset = c->Rsp;
133 frame.AddrFrame.Offset = c->Rbp;
134 const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
135 #endif
136
137 while (StackWalk64(machineType,
138 GetCurrentProcess(),
139 GetCurrentThread(),
140 &frame,
141 c,
142 NULL,
143 SymFunctionTableAccess64,
144 SymGetModuleBase64,
145 NULL)) {
146 // Buffer to store symbol name in.
147 static const int kMaxNameLength = 1024;
148 uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength];
149 sk_bzero(buffer, sizeof(buffer));
150
151 // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in
152 // how much space it can use.
153 IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*> (&buffer);
154 symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
155 symbol->MaxNameLength = kMaxNameLength - 1;
156
157 // Translate the current PC into a symbol and byte offset from t he symbol.
158 DWORD64 offset;
159 SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symb ol);
160
161 SkDebugf("%s +%x\n", symbol->Name, offset);
162 }
163
164 // Exit NOW. Don't notify other threads, don't call anything regist ered with atexit().
165 _exit(1);
166
167 // The compiler wants us to return something. This is what we'd do
168 // if we didn't _exit().
169 return EXCEPTION_EXECUTE_HANDLER;
170 }
171
172 void SetupCrashHandler() {
173 SetUnhandledExceptionFilter(handler);
174 }
175
176 #else // We asked for SK_CRASH_HANDLER, but it's not Mac, Linux, or Windows . Sorry!
177
178 void SetupCrashHandler() { }
179
180 #endif
181 #endif // SK_CRASH_HANDLER
OLDNEW
« no previous file with comments | « tools/CrashHandler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698