blob: 15a5fff00b47dd60f382eae9f5698c580a29519a [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 Hughesffe67362011-07-17 12:09:27 -070022
23#include "logging.h"
Elliott Hughesffe67362011-07-17 12:09:27 -070024#include "stringprintf.h"
25
26namespace art {
27
Elliott Hughes457005c2012-04-16 13:54:25 -070028static std::string Demangle(const std::string& mangled_name) {
Elliott Hughes82870722011-08-29 19:04:51 -070029 if (mangled_name.empty()) {
30 return "??";
31 }
32
33 // http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
34 int status;
Elliott Hughes34023802011-08-30 12:06:17 -070035 char* name(abi::__cxa_demangle(mangled_name.c_str(), NULL, NULL, &status));
36 if (name != NULL) {
37 std::string result(name);
38 free(name);
39 return result;
Elliott Hughes82870722011-08-29 19:04:51 -070040 }
41
42 return mangled_name + "()";
43}
44
Elliott Hughes457005c2012-04-16 13:54:25 -070045static void Backtrace() {
Elliott Hughesffe67362011-07-17 12:09:27 -070046 // Get the raw stack frames.
47 size_t MAX_STACK_FRAMES = 64;
48 void* frames[MAX_STACK_FRAMES];
49 size_t frame_count = backtrace(frames, MAX_STACK_FRAMES);
50
51 // Turn them into something human-readable with symbols.
Elliott Hughes34023802011-08-30 12:06:17 -070052 char** symbols = backtrace_symbols(frames, frame_count);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070053 if (symbols == NULL) {
Elliott Hughesffe67362011-07-17 12:09:27 -070054 PLOG(ERROR) << "backtrace_symbols failed";
55 return;
56 }
57
Elliott Hughes82870722011-08-29 19:04:51 -070058 // backtrace_symbols(3) gives us lines like this:
59 // "/usr/local/google/home/enh/a1/out/host/linux-x86/bin/../lib/libartd.so(_ZN3art7Runtime13PlatformAbortEPKci+0x15b) [0xf76c5af3]"
Elliott Hughesa0957642011-09-02 14:27:33 -070060 // "[0xf7b62057]"
Elliott Hughes82870722011-08-29 19:04:51 -070061
62 // We extract the pieces and demangle, so we can produce output like this:
Elliott Hughes362f9bc2011-10-17 18:56:41 -070063 // libartd.so:-1] #00 art::Runtime::PlatformAbort(char const*, int) +0x15b [0xf770dd51]
Elliott Hughes82870722011-08-29 19:04:51 -070064
Elliott Hughesffe67362011-07-17 12:09:27 -070065 for (size_t i = 0; i < frame_count; ++i) {
Elliott Hughes34023802011-08-30 12:06:17 -070066 std::string text(symbols[i]);
Elliott Hughesa0957642011-09-02 14:27:33 -070067 std::string filename("??");
68 std::string function_name;
Elliott Hughes82870722011-08-29 19:04:51 -070069
70 size_t index = text.find('(');
Elliott Hughesa0957642011-09-02 14:27:33 -070071 if (index != std::string::npos) {
72 filename = text.substr(0, index);
73 text.erase(0, index + 1);
Elliott Hughes82870722011-08-29 19:04:51 -070074
Elliott Hughesa0957642011-09-02 14:27:33 -070075 index = text.find_first_of("+)");
76 function_name = Demangle(text.substr(0, index));
77 text.erase(0, index);
78 index = text.find(')');
79 text.erase(index, 1);
80 }
Elliott Hughesad6c9c32012-01-19 17:39:12 -080081 std::string log_line(StringPrintf("\t#%02zd ", i) + function_name + text);
Elliott Hughes9ee5f9c2012-02-03 18:33:16 -080082 LogMessage(filename.c_str(), -1, INTERNAL_FATAL, -1).stream() << log_line;
Elliott Hughesffe67362011-07-17 12:09:27 -070083 }
Elliott Hughes34023802011-08-30 12:06:17 -070084
85 free(symbols);
Elliott Hughesffe67362011-07-17 12:09:27 -070086}
87
Elliott Hughes457005c2012-04-16 13:54:25 -070088static const char* GetSignalCodeName(int signal_number, int signal_code) {
89 // Try the signal-specific codes...
90 switch (signal_number) {
91 case SIGILL:
92 switch (signal_code) {
93 case ILL_ILLOPC: return "ILL_ILLOPC";
94 case ILL_ILLOPN: return "ILL_ILLOPN";
95 case ILL_ILLADR: return "ILL_ILLADR";
96 case ILL_ILLTRP: return "ILL_ILLTRP";
97 case ILL_PRVOPC: return "ILL_PRVOPC";
98 case ILL_PRVREG: return "ILL_PRVREG";
99 case ILL_COPROC: return "ILL_COPROC";
100 case ILL_BADSTK: return "ILL_BADSTK";
101 }
102 break;
103 case SIGBUS:
104 switch (signal_code) {
105 case BUS_ADRALN: return "BUS_ADRALN";
106 case BUS_ADRERR: return "BUS_ADRERR";
107 case BUS_OBJERR: return "BUS_OBJERR";
108 }
109 break;
110 case SIGFPE:
111 switch (signal_code) {
112 case FPE_INTDIV: return "FPE_INTDIV";
113 case FPE_INTOVF: return "FPE_INTOVF";
114 case FPE_FLTDIV: return "FPE_FLTDIV";
115 case FPE_FLTOVF: return "FPE_FLTOVF";
116 case FPE_FLTUND: return "FPE_FLTUND";
117 case FPE_FLTRES: return "FPE_FLTRES";
118 case FPE_FLTINV: return "FPE_FLTINV";
119 case FPE_FLTSUB: return "FPE_FLTSUB";
120 }
121 break;
122 case SIGSEGV:
123 switch (signal_code) {
124 case SEGV_MAPERR: return "SEGV_MAPERR";
125 case SEGV_ACCERR: return "SEGV_ACCERR";
126 }
127 break;
128 case SIGTRAP:
129 switch (signal_code) {
130 case TRAP_BRKPT: return "TRAP_BRKPT";
131 case TRAP_TRACE: return "TRAP_TRACE";
132 }
133 break;
134 }
135 // Then the other codes...
136 switch (signal_code) {
137 case SI_USER: return "SI_USER";
138 case SI_KERNEL: return "SI_KERNEL";
139 case SI_QUEUE: return "SI_QUEUE";
140 case SI_TIMER: return "SI_TIMER";
141 case SI_MESGQ: return "SI_MESGQ";
142 case SI_ASYNCIO: return "SI_ASYNCIO";
143 case SI_SIGIO: return "SI_SIGIO";
144 case SI_TKILL: return "SI_TKILL";
145 }
146 // Then give up...
147 return "?";
148}
149
150static void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void*) {
151 const char* signal_name = "?";
152 bool has_address = false;
153 if (signal_number == SIGILL) {
154 signal_name = "SIGILL";
155 has_address = true;
156 } else if (signal_number == SIGTRAP) {
157 signal_name = "SIGTRAP";
158 } else if (signal_number == SIGABRT) {
159 signal_name = "SIGABRT";
160 } else if (signal_number == SIGBUS) {
161 signal_name = "SIGBUS";
162 has_address = true;
163 } else if (signal_number == SIGFPE) {
164 signal_name = "SIGFPE";
165 has_address = true;
166 } else if (signal_number == SIGSEGV) {
167 signal_name = "SIGSEGV";
168 has_address = true;
169 } else if (signal_number == SIGSTKFLT) {
170 signal_name = "SIGSTKFLT";
171 } else if (signal_number == SIGPIPE) {
172 signal_name = "SIGPIPE";
173 }
174
175 LOG(INTERNAL_FATAL) << "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"
176 << StringPrintf("Fatal signal %d (%s), code %d (%s)",
177 signal_number, signal_name,
178 info->si_code,
179 GetSignalCodeName(signal_number, info->si_code))
180 << (has_address ? StringPrintf(" fault addr %p", info->si_addr) : "");
181 Backtrace();
182
183 // TODO: make this part optional, like it is on the device?
184 // Wait for debugger to attach.
185 LOG(INTERNAL_FATAL) << "********************************************************\n"
186 << "* Process " << getpid() << " has been suspended while crashing. Attach gdb:\n"
187 << "* gdb -p " << getpid() << "\n"
188 << "********************************************************\n";
189 while (true) {
190 }
191}
192
193void Runtime::PlatformAbort(const char* /*file*/, int /*line_number*/) {
194 // On the host, we don't have debuggerd to dump a stack for us when we LOG(FATAL).
195 Backtrace();
196}
197
198void Runtime::InitPlatformSignalHandlers() {
199 // On the host, we don't have debuggerd to dump a stack for us when something unexpected happens.
200 struct sigaction action;
201 memset(&action, 0, sizeof(action));
202 sigemptyset(&action.sa_mask);
203 action.sa_sigaction = HandleUnexpectedSignal;
204 action.sa_flags = SA_RESTART | SA_SIGINFO;
205
206 int rc = 0;
207 rc += sigaction(SIGILL, &action, NULL);
208 rc += sigaction(SIGTRAP, &action, NULL);
209 rc += sigaction(SIGABRT, &action, NULL);
210 rc += sigaction(SIGBUS, &action, NULL);
211 rc += sigaction(SIGFPE, &action, NULL);
212 rc += sigaction(SIGSEGV, &action, NULL);
213 rc += sigaction(SIGSTKFLT, &action, NULL);
214 rc += sigaction(SIGPIPE, &action, NULL);
215 CHECK_EQ(rc, 0);
216}
217
Elliott Hughesffe67362011-07-17 12:09:27 -0700218} // namespace art