1 /* 2 * Copyright (C) 2017 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 */ 16 17 #include <cxxabi.h> 18 #include <dlfcn.h> 19 #include <signal.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <sys/syscall.h> 25 #include <sys/types.h> 26 #include <unistd.h> 27 #include <unwind.h> 28 29 #include "perfetto/base/build_config.h" 30 31 // Some glibc headers hit this when using signals. 32 #pragma GCC diagnostic push 33 #if defined(__clang__) 34 #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" 35 #endif 36 37 #if defined(NDEBUG) 38 #error This translation unit should not be used in release builds 39 #endif 40 41 #if PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) || \ 42 PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) 43 #error This translation unit should not be used in non-standalone builds 44 #endif 45 46 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 47 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 48 #include <backtrace.h> 49 #endif 50 51 namespace { 52 53 constexpr size_t kDemangledNameLen = 4096; 54 55 bool g_sighandler_registered = false; 56 char* g_demangled_name = nullptr; 57 58 struct SigHandler { 59 int sig_num; 60 struct sigaction old_handler; 61 }; 62 63 SigHandler g_signals[] = {{SIGSEGV, {}}, {SIGILL, {}}, {SIGTRAP, {}}, 64 {SIGABRT, {}}, {SIGBUS, {}}, {SIGFPE, {}}}; 65 66 template <typename T> 67 void Print(const T& str) { 68 write(STDERR_FILENO, str, sizeof(str)); 69 } 70 71 template <typename T> 72 void PrintHex(T n) { 73 for (unsigned i = 0; i < sizeof(n) * 8; i += 4) { 74 char nibble = static_cast<char>(n >> (sizeof(n) * 8 - i - 4)) & 0x0F; 75 char c = (nibble < 10) ? '0' + nibble : 'A' + nibble - 10; 76 write(STDERR_FILENO, &c, 1); 77 } 78 } 79 80 struct StackCrawlState { 81 StackCrawlState(uintptr_t* frames_arg, size_t max_depth_arg) 82 : frames(frames_arg), 83 frame_count(0), 84 max_depth(max_depth_arg), 85 skip_count(1) {} 86 87 uintptr_t* frames; 88 size_t frame_count; 89 size_t max_depth; 90 size_t skip_count; 91 }; 92 93 _Unwind_Reason_Code TraceStackFrame(_Unwind_Context* context, void* arg) { 94 StackCrawlState* state = static_cast<StackCrawlState*>(arg); 95 uintptr_t ip = _Unwind_GetIP(context); 96 97 if (ip != 0 && state->skip_count) { 98 state->skip_count--; 99 return _URC_NO_REASON; 100 } 101 102 state->frames[state->frame_count++] = ip; 103 if (state->frame_count >= state->max_depth) 104 return _URC_END_OF_STACK; 105 return _URC_NO_REASON; 106 } 107 108 // Note: use only async-safe functions inside this. 109 void SignalHandler(int sig_num, siginfo_t* info, void* /*ucontext*/) { 110 // Restore the old handlers. 111 for (size_t i = 0; i < sizeof(g_signals) / sizeof(g_signals[0]); i++) 112 sigaction(g_signals[i].sig_num, &g_signals[i].old_handler, nullptr); 113 114 Print("\n------------------ BEGINNING OF CRASH ------------------\n"); 115 Print("Signal: "); 116 if (sig_num == SIGSEGV) { 117 Print("Segmentation fault"); 118 } else if (sig_num == SIGILL) { 119 Print("Illegal instruction (possibly unaligned access)"); 120 } else if (sig_num == SIGTRAP) { 121 Print("Trap"); 122 } else if (sig_num == SIGABRT) { 123 Print("Abort"); 124 } else if (sig_num == SIGBUS) { 125 Print("Bus Error (possibly unmapped memory access)"); 126 } else if (sig_num == SIGFPE) { 127 Print("Floating point exception"); 128 } else { 129 Print("Unexpected signal "); 130 PrintHex(static_cast<uint32_t>(sig_num)); 131 } 132 133 Print("\n"); 134 135 Print("Fault addr: "); 136 PrintHex(reinterpret_cast<uintptr_t>(info->si_addr)); 137 Print("\n\nBacktrace:\n"); 138 139 const size_t kMaxFrames = 64; 140 uintptr_t frames[kMaxFrames]; 141 StackCrawlState unwind_state(frames, kMaxFrames); 142 _Unwind_Backtrace(&TraceStackFrame, &unwind_state); 143 144 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 145 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 146 auto bt_error = [](void*, const char* msg, int) { Print(msg); }; 147 struct backtrace_state* bt_state = 148 backtrace_create_state(nullptr, 0, bt_error, nullptr); 149 #endif 150 151 for (uint8_t i = 0; i < unwind_state.frame_count; i++) { 152 struct SymbolInfo { 153 char sym_name[255]; 154 char file_name[255]; 155 }; 156 SymbolInfo sym{{}, {}}; 157 158 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 159 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 160 auto symbolize_callback = [](void* data, uintptr_t /*pc*/, 161 const char* filename, int lineno, 162 const char* function) -> int { 163 SymbolInfo* psym = reinterpret_cast<SymbolInfo*>(data); 164 if (function) 165 strncpy(psym->sym_name, function, sizeof(psym->sym_name)); 166 if (filename) { 167 snprintf(psym->file_name, sizeof(psym->file_name), "%s:%d", filename, 168 lineno); 169 } 170 return 0; 171 }; 172 backtrace_pcinfo(bt_state, frames[i], symbolize_callback, bt_error, &sym); 173 #else 174 Dl_info dl_info = {}; 175 int res = dladdr(reinterpret_cast<void*>(frames[i]), &dl_info); 176 if (res && dl_info.dli_sname) 177 strncpy(sym.sym_name, dl_info.dli_sname, sizeof(sym.sym_name)); 178 #endif 179 180 Print("\n#"); 181 PrintHex(i); 182 Print(" "); 183 184 if (sym.sym_name[0]) { 185 int ignored; 186 size_t len = kDemangledNameLen; 187 char* demangled = 188 abi::__cxa_demangle(sym.sym_name, g_demangled_name, &len, &ignored); 189 if (demangled) { 190 strncpy(sym.sym_name, demangled, sizeof(sym.sym_name)); 191 // In the exceptional case of demangling something > kDemangledNameLen, 192 // __cxa_demangle will realloc(). In that case the malloc()-ed pointer 193 // might be moved. 194 g_demangled_name = demangled; 195 } 196 write(STDERR_FILENO, sym.sym_name, strlen(sym.sym_name)); 197 } else { 198 Print("0x"); 199 PrintHex(frames[i]); 200 } 201 if (sym.file_name[0]) { 202 Print("\n "); 203 write(STDERR_FILENO, sym.file_name, strlen(sym.file_name)); 204 } 205 Print("\n"); 206 } 207 208 Print("------------------ END OF CRASH ------------------\n"); 209 210 // info->si_code <= 0 iff SI_FROMUSER (SI_FROMKERNEL otherwise). 211 if (info->si_code <= 0 || sig_num == SIGABRT) { 212 // This signal was triggered by somebody sending us the signal with kill(). 213 // In order to retrigger it, we have to queue a new signal by calling 214 // kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is 215 // due to the kernel sending a SIGABRT from a user request via SysRQ. 216 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) 217 if (kill(getpid(), sig_num) < 0) { 218 #else 219 if (syscall(__NR_tgkill, getpid(), syscall(__NR_gettid), sig_num) < 0) { 220 #endif 221 // If we failed to kill ourselves (e.g. because a sandbox disallows us 222 // to do so), we instead resort to terminating our process. This will 223 // result in an incorrect exit code. 224 _exit(1); 225 } 226 } 227 } 228 229 // __attribute__((constructor)) causes a static initializer that automagically 230 // early runs this function before the main(). 231 void __attribute__((constructor)) EnableStacktraceOnCrashForDebug(); 232 233 void EnableStacktraceOnCrashForDebug() { 234 if (g_sighandler_registered) 235 return; 236 g_sighandler_registered = true; 237 238 // Pre-allocate the string for __cxa_demangle() to reduce the risk of that 239 // invoking realloc() within the signal handler. 240 g_demangled_name = reinterpret_cast<char*>(malloc(kDemangledNameLen)); 241 struct sigaction sigact = {}; 242 sigact.sa_sigaction = &SignalHandler; 243 sigact.sa_flags = static_cast<decltype(sigact.sa_flags)>( 244 SA_RESTART | SA_SIGINFO | SA_RESETHAND); 245 for (size_t i = 0; i < sizeof(g_signals) / sizeof(g_signals[0]); i++) 246 sigaction(g_signals[i].sig_num, &sigact, &g_signals[i].old_handler); 247 } 248 249 } // namespace 250 251 #pragma GCC diagnostic pop 252