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