blob: 3e39fa2510bf98ed0e879d97067525afa4fcc5ce [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Elliott Hughesffe67362011-07-17 12:09:27 -070016
17#include "runtime.h"
18
Elliott Hughes82870722011-08-29 19:04:51 -070019#include <cxxabi.h>
Elliott Hughesffe67362011-07-17 12:09:27 -070020#include <execinfo.h>
Elliott Hughes457005c2012-04-16 13:54:25 -070021#include <signal.h>
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070022#include <string.h>
Elliott Hughesffe67362011-07-17 12:09:27 -070023
24#include "logging.h"
Elliott Hughesffe67362011-07-17 12:09:27 -070025#include "stringprintf.h"
26
27namespace art {
28
Elliott Hughes457005c2012-04-16 13:54:25 -070029static std::string Demangle(const std::string& mangled_name) {
Elliott Hughes82870722011-08-29 19:04:51 -070030 if (mangled_name.empty()) {
31 return "??";
32 }
33
34 // http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
35 int status;
Elliott Hughes34023802011-08-30 12:06:17 -070036 char* name(abi::__cxa_demangle(mangled_name.c_str(), NULL, NULL, &status));
37 if (name != NULL) {
38 std::string result(name);
39 free(name);
40 return result;
Elliott Hughes82870722011-08-29 19:04:51 -070041 }
42
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070043 return mangled_name;
Elliott Hughes82870722011-08-29 19:04:51 -070044}
45
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070046struct Backtrace {
47 void Dump(std::ostream& os) {
48 // Get the raw stack frames.
49 size_t MAX_STACK_FRAMES = 128;
50 void* frames[MAX_STACK_FRAMES];
51 size_t frame_count = backtrace(frames, MAX_STACK_FRAMES);
52 if (frame_count == 0) {
53 os << "--- backtrace(3) returned no frames";
54 return;
55 }
Elliott Hughesffe67362011-07-17 12:09:27 -070056
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070057 // Turn them into something human-readable with symbols.
58 char** symbols = backtrace_symbols(frames, frame_count);
59 if (symbols == NULL) {
60 os << "--- backtrace_symbols(3) failed";
61 return;
62 }
Elliott Hughesffe67362011-07-17 12:09:27 -070063
Elliott Hughes82870722011-08-29 19:04:51 -070064
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070065 // Parse the backtrace strings and demangle, so we can produce output like this:
66 // ] #00 art::Runtime::Abort(char const*, int)+0x15b [0xf770dd51] (libartd.so)
67 for (size_t i = 0; i < frame_count; ++i) {
68 std::string text(symbols[i]);
69 std::string filename("???");
70 std::string function_name;
Elliott Hughes82870722011-08-29 19:04:51 -070071
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070072#if defined(__APPLE__)
73 // backtrace_symbols(3) gives us lines like this on Mac OS:
74 // "0 libartd.dylib 0x001cd29a _ZN3art9Backtrace4DumpERSo + 40>"
75 // "3 ??? 0xffffffff 0x0 + 4294967295>"
76 text.erase(0, 4);
77 size_t index = text.find(' ');
Elliott Hughesa0957642011-09-02 14:27:33 -070078 filename = text.substr(0, index);
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070079 text.erase(0, 40 - 4);
80 index = text.find(' ');
81 std::string address(text.substr(0, index));
Elliott Hughesa0957642011-09-02 14:27:33 -070082 text.erase(0, index + 1);
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070083 index = text.find(' ');
Elliott Hughesa0957642011-09-02 14:27:33 -070084 function_name = Demangle(text.substr(0, index));
85 text.erase(0, index);
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070086 text += " [" + address + "]";
87#else
88 // backtrace_symbols(3) gives us lines like this on Linux:
89 // "/usr/local/google/home/enh/a1/out/host/linux-x86/bin/../lib/libartd.so(_ZN3art7Runtime5AbortEPKci+0x15b) [0xf76c5af3]"
90 // "[0xf7b62057]"
91 size_t index = text.find('(');
92 if (index != std::string::npos) {
93 filename = text.substr(0, index);
94 text.erase(0, index + 1);
Elliott Hughes34023802011-08-30 12:06:17 -070095
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070096 index = text.find_first_of("+)");
97 function_name = Demangle(text.substr(0, index));
98 text.erase(0, index);
99 index = text.find(')');
100 text.erase(index, 1);
101 }
102#endif
103
104 const char* last_slash = strrchr(filename.c_str(), '/');
105 const char* so_name = (last_slash == NULL) ? filename.c_str() : last_slash + 1;
106 os << StringPrintf("\t#%02zd ", i) << function_name << text << " (" << so_name << ")\n";
107 }
108
109 free(symbols);
110 }
111};
112
113static const char* GetSignalName(int signal_number) {
114 switch (signal_number) {
115 case SIGABRT: return "SIGABRT";
116 case SIGBUS: return "SIGBUS";
117 case SIGFPE: return "SIGFPE";
118 case SIGILL: return "SIGILL";
119 case SIGPIPE: return "SIGPIPE";
120 case SIGSEGV: return "SIGSEGV";
Elliott Hughes833770b2012-05-01 15:41:03 -0700121#if defined(SIGSTKFLT)
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700122 case SIGSTKFLT: return "SIGSTKFLT";
123#endif
124 case SIGTRAP: return "SIGTRAP";
125 }
126 return "??";
Elliott Hughesffe67362011-07-17 12:09:27 -0700127}
128
Elliott Hughes457005c2012-04-16 13:54:25 -0700129static const char* GetSignalCodeName(int signal_number, int signal_code) {
130 // Try the signal-specific codes...
131 switch (signal_number) {
132 case SIGILL:
133 switch (signal_code) {
134 case ILL_ILLOPC: return "ILL_ILLOPC";
135 case ILL_ILLOPN: return "ILL_ILLOPN";
136 case ILL_ILLADR: return "ILL_ILLADR";
137 case ILL_ILLTRP: return "ILL_ILLTRP";
138 case ILL_PRVOPC: return "ILL_PRVOPC";
139 case ILL_PRVREG: return "ILL_PRVREG";
140 case ILL_COPROC: return "ILL_COPROC";
141 case ILL_BADSTK: return "ILL_BADSTK";
142 }
143 break;
144 case SIGBUS:
145 switch (signal_code) {
146 case BUS_ADRALN: return "BUS_ADRALN";
147 case BUS_ADRERR: return "BUS_ADRERR";
148 case BUS_OBJERR: return "BUS_OBJERR";
149 }
150 break;
151 case SIGFPE:
152 switch (signal_code) {
153 case FPE_INTDIV: return "FPE_INTDIV";
154 case FPE_INTOVF: return "FPE_INTOVF";
155 case FPE_FLTDIV: return "FPE_FLTDIV";
156 case FPE_FLTOVF: return "FPE_FLTOVF";
157 case FPE_FLTUND: return "FPE_FLTUND";
158 case FPE_FLTRES: return "FPE_FLTRES";
159 case FPE_FLTINV: return "FPE_FLTINV";
160 case FPE_FLTSUB: return "FPE_FLTSUB";
161 }
162 break;
163 case SIGSEGV:
164 switch (signal_code) {
165 case SEGV_MAPERR: return "SEGV_MAPERR";
166 case SEGV_ACCERR: return "SEGV_ACCERR";
167 }
168 break;
169 case SIGTRAP:
170 switch (signal_code) {
171 case TRAP_BRKPT: return "TRAP_BRKPT";
172 case TRAP_TRACE: return "TRAP_TRACE";
173 }
174 break;
175 }
176 // Then the other codes...
177 switch (signal_code) {
178 case SI_USER: return "SI_USER";
Elliott Hughesac8097f2012-04-16 14:59:44 -0700179#if defined(SI_KERNEL)
Elliott Hughes457005c2012-04-16 13:54:25 -0700180 case SI_KERNEL: return "SI_KERNEL";
Elliott Hughesac8097f2012-04-16 14:59:44 -0700181#endif
Elliott Hughes457005c2012-04-16 13:54:25 -0700182 case SI_QUEUE: return "SI_QUEUE";
183 case SI_TIMER: return "SI_TIMER";
184 case SI_MESGQ: return "SI_MESGQ";
185 case SI_ASYNCIO: return "SI_ASYNCIO";
Elliott Hughesac8097f2012-04-16 14:59:44 -0700186#if defined(SI_SIGIO)
Elliott Hughes457005c2012-04-16 13:54:25 -0700187 case SI_SIGIO: return "SI_SIGIO";
Elliott Hughesac8097f2012-04-16 14:59:44 -0700188#endif
189#if defined(SI_TKILL)
Elliott Hughes457005c2012-04-16 13:54:25 -0700190 case SI_TKILL: return "SI_TKILL";
Elliott Hughesac8097f2012-04-16 14:59:44 -0700191#endif
Elliott Hughes457005c2012-04-16 13:54:25 -0700192 }
193 // Then give up...
194 return "?";
195}
196
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700197struct UContext {
198 UContext(void* raw_context) : context(reinterpret_cast<ucontext_t*>(raw_context)->uc_mcontext) {}
199
200 void Dump(std::ostream& os) {
201 // TODO: support non-x86 hosts (not urgent because this code doesn't run on targets).
202#if defined(__APPLE__)
203 DumpRegister32(os, "eax", context->__ss.__eax);
204 DumpRegister32(os, "ebx", context->__ss.__ebx);
205 DumpRegister32(os, "ecx", context->__ss.__ecx);
206 DumpRegister32(os, "edx", context->__ss.__edx);
207 os << '\n';
208
209 DumpRegister32(os, "edi", context->__ss.__edi);
210 DumpRegister32(os, "esi", context->__ss.__esi);
211 DumpRegister32(os, "ebp", context->__ss.__ebp);
212 DumpRegister32(os, "esp", context->__ss.__esp);
213 os << '\n';
214
215 DumpRegister32(os, "eip", context->__ss.__eip);
216 DumpRegister32(os, "eflags", context->__ss.__eflags);
217 os << '\n';
218
219 DumpRegister32(os, "cs", context->__ss.__cs);
220 DumpRegister32(os, "ds", context->__ss.__ds);
221 DumpRegister32(os, "es", context->__ss.__es);
222 DumpRegister32(os, "fs", context->__ss.__fs);
223 os << '\n';
224 DumpRegister32(os, "gs", context->__ss.__gs);
225 DumpRegister32(os, "ss", context->__ss.__ss);
226#else
227 DumpRegister32(os, "eax", context.gregs[REG_EAX]);
228 DumpRegister32(os, "ebx", context.gregs[REG_EBX]);
229 DumpRegister32(os, "ecx", context.gregs[REG_ECX]);
230 DumpRegister32(os, "edx", context.gregs[REG_EDX]);
231 os << '\n';
232
233 DumpRegister32(os, "edi", context.gregs[REG_EDI]);
234 DumpRegister32(os, "esi", context.gregs[REG_ESI]);
235 DumpRegister32(os, "ebp", context.gregs[REG_EBP]);
236 DumpRegister32(os, "esp", context.gregs[REG_ESP]);
237 os << '\n';
238
239 DumpRegister32(os, "eip", context.gregs[REG_EIP]);
240 DumpRegister32(os, "eflags", context.gregs[REG_EFL]);
241 os << '\n';
242
243 DumpRegister32(os, "cs", context.gregs[REG_CS]);
244 DumpRegister32(os, "ds", context.gregs[REG_DS]);
245 DumpRegister32(os, "es", context.gregs[REG_ES]);
246 DumpRegister32(os, "fs", context.gregs[REG_FS]);
247 os << '\n';
248 DumpRegister32(os, "gs", context.gregs[REG_GS]);
249 DumpRegister32(os, "ss", context.gregs[REG_SS]);
Elliott Hughesac8097f2012-04-16 14:59:44 -0700250#endif
Elliott Hughes457005c2012-04-16 13:54:25 -0700251 }
252
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700253 void DumpRegister32(std::ostream& os, const char* name, uint32_t value) {
254 os << StringPrintf(" %6s: 0x%08x", name, value);
255 }
256
257 mcontext_t& context;
258};
259
260static void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) {
Elliott Hughesd06a6c72012-05-30 17:59:06 -0700261 static Mutex unexpected_signal_lock("unexpected signal lock");
262 MutexLock mu(unexpected_signal_lock);
263
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700264 bool has_address = (signal_number == SIGILL || signal_number == SIGBUS ||
265 signal_number == SIGFPE || signal_number == SIGSEGV);
266
267 UContext thread_context(raw_context);
268 Backtrace thread_backtrace;
Elliott Hughes8593fdb2012-04-21 20:53:44 -0700269
Elliott Hughes457005c2012-04-16 13:54:25 -0700270 LOG(INTERNAL_FATAL) << "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"
271 << StringPrintf("Fatal signal %d (%s), code %d (%s)",
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700272 signal_number, GetSignalName(signal_number),
Elliott Hughes457005c2012-04-16 13:54:25 -0700273 info->si_code,
274 GetSignalCodeName(signal_number, info->si_code))
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700275 << (has_address ? StringPrintf(" fault addr %p", info->si_addr) : "") << "\n"
276 << "Registers:\n" << Dumpable<UContext>(thread_context) << "\n"
277 << "Backtrace:\n" << Dumpable<Backtrace>(thread_backtrace);
Elliott Hughes457005c2012-04-16 13:54:25 -0700278
Elliott Hughes2554cb92012-04-18 17:19:26 -0700279 // TODO: instead, get debuggerd running on the host, try to connect, and hang around on success.
280 if (getenv("debug_db_uid") != NULL) {
281 LOG(INTERNAL_FATAL) << "********************************************************\n"
282 << "* Process " << getpid() << " has been suspended while crashing. Attach gdb:\n"
283 << "* gdb -p " << getpid() << "\n"
284 << "********************************************************\n";
285 // Wait for debugger to attach.
286 while (true) {
287 }
Elliott Hughes457005c2012-04-16 13:54:25 -0700288 }
Elliott Hughesd06a6c72012-05-30 17:59:06 -0700289
290 // Remove our signal handler for this signal...
291 struct sigaction action;
292 memset(&action, 0, sizeof(action));
293 sigemptyset(&action.sa_mask);
294 action.sa_handler = SIG_DFL;
295 sigaction(signal_number, &action, NULL);
296 // ...and re-raise so we die with the appropriate status.
297 kill(getpid(), signal_number);
Elliott Hughes457005c2012-04-16 13:54:25 -0700298}
299
Elliott Hughes457005c2012-04-16 13:54:25 -0700300void Runtime::InitPlatformSignalHandlers() {
301 // On the host, we don't have debuggerd to dump a stack for us when something unexpected happens.
302 struct sigaction action;
303 memset(&action, 0, sizeof(action));
304 sigemptyset(&action.sa_mask);
305 action.sa_sigaction = HandleUnexpectedSignal;
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700306 // Use the three-argument sa_sigaction handler.
307 action.sa_flags |= SA_SIGINFO;
Elliott Hughesd06a6c72012-05-30 17:59:06 -0700308#if !defined(__APPLE__)
309 // Use the alternate signal stack so we can catch stack overflows.
310 action.sa_flags |= SA_ONSTACK;
311#endif
Elliott Hughes457005c2012-04-16 13:54:25 -0700312
313 int rc = 0;
314 rc += sigaction(SIGILL, &action, NULL);
315 rc += sigaction(SIGTRAP, &action, NULL);
316 rc += sigaction(SIGABRT, &action, NULL);
317 rc += sigaction(SIGBUS, &action, NULL);
318 rc += sigaction(SIGFPE, &action, NULL);
Elliott Hughesac8097f2012-04-16 14:59:44 -0700319#if defined(SIGSTKFLT)
Elliott Hughes457005c2012-04-16 13:54:25 -0700320 rc += sigaction(SIGSTKFLT, &action, NULL);
Elliott Hughesac8097f2012-04-16 14:59:44 -0700321#endif
Elliott Hughes457005c2012-04-16 13:54:25 -0700322 rc += sigaction(SIGPIPE, &action, NULL);
Elliott Hughes6c1c69e2012-04-23 16:12:51 -0700323
324 // Use the alternate signal stack so we can catch stack overflows.
325 // On Mac OS 10.7, backtrace(3) is broken and will return no frames when called from the alternate stack,
326 // so we only use the alternate stack for SIGSEGV so that we at least get backtraces for other signals.
327 // (glibc does the right thing, so we could use the alternate stack for all signals there.)
328 action.sa_flags |= SA_ONSTACK;
329 rc += sigaction(SIGSEGV, &action, NULL);
330
Elliott Hughes457005c2012-04-16 13:54:25 -0700331 CHECK_EQ(rc, 0);
332}
333
Elliott Hughesffe67362011-07-17 12:09:27 -0700334} // namespace art