xref: /aosp_15_r20/tools/netsim/src/util/crash_report.cc (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1*cf78ab8cSAndroid Build Coastguard Worker // Copyright 2023 The Android Open Source Project
2*cf78ab8cSAndroid Build Coastguard Worker //
3*cf78ab8cSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*cf78ab8cSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*cf78ab8cSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*cf78ab8cSAndroid Build Coastguard Worker //
7*cf78ab8cSAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*cf78ab8cSAndroid Build Coastguard Worker //
9*cf78ab8cSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*cf78ab8cSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*cf78ab8cSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*cf78ab8cSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*cf78ab8cSAndroid Build Coastguard Worker // limitations under the License.
14*cf78ab8cSAndroid Build Coastguard Worker 
15*cf78ab8cSAndroid Build Coastguard Worker #include "util/crash_report.h"
16*cf78ab8cSAndroid Build Coastguard Worker 
17*cf78ab8cSAndroid Build Coastguard Worker #include <fcntl.h>
18*cf78ab8cSAndroid Build Coastguard Worker #include <stdio.h>
19*cf78ab8cSAndroid Build Coastguard Worker #include <unistd.h>
20*cf78ab8cSAndroid Build Coastguard Worker #if defined(_WIN32)
21*cf78ab8cSAndroid Build Coastguard Worker #include <windows.h>
22*cf78ab8cSAndroid Build Coastguard Worker #endif
23*cf78ab8cSAndroid Build Coastguard Worker 
24*cf78ab8cSAndroid Build Coastguard Worker #if defined(__linux__)
25*cf78ab8cSAndroid Build Coastguard Worker 
26*cf78ab8cSAndroid Build Coastguard Worker #ifndef NETSIM_ANDROID_EMULATOR
27*cf78ab8cSAndroid Build Coastguard Worker #include <client/linux/handler/exception_handler.h>
28*cf78ab8cSAndroid Build Coastguard Worker #include <fmt/format.h>
29*cf78ab8cSAndroid Build Coastguard Worker #include <unwindstack/AndroidUnwinder.h>
30*cf78ab8cSAndroid Build Coastguard Worker 
31*cf78ab8cSAndroid Build Coastguard Worker #include <iostream>
32*cf78ab8cSAndroid Build Coastguard Worker #else
33*cf78ab8cSAndroid Build Coastguard Worker #include <signal.h>
34*cf78ab8cSAndroid Build Coastguard Worker #endif
35*cf78ab8cSAndroid Build Coastguard Worker 
36*cf78ab8cSAndroid Build Coastguard Worker #include <execinfo.h>
37*cf78ab8cSAndroid Build Coastguard Worker #include <unistd.h>
38*cf78ab8cSAndroid Build Coastguard Worker 
39*cf78ab8cSAndroid Build Coastguard Worker #include <cstdio>
40*cf78ab8cSAndroid Build Coastguard Worker #include <cstdlib>
41*cf78ab8cSAndroid Build Coastguard Worker #endif
42*cf78ab8cSAndroid Build Coastguard Worker 
43*cf78ab8cSAndroid Build Coastguard Worker #include "util/filesystem.h"
44*cf78ab8cSAndroid Build Coastguard Worker #include "util/ini_file.h"
45*cf78ab8cSAndroid Build Coastguard Worker #include "util/log.h"
46*cf78ab8cSAndroid Build Coastguard Worker 
47*cf78ab8cSAndroid Build Coastguard Worker namespace netsim {
48*cf78ab8cSAndroid Build Coastguard Worker namespace {
49*cf78ab8cSAndroid Build Coastguard Worker 
50*cf78ab8cSAndroid Build Coastguard Worker #if defined(__linux__)
51*cf78ab8cSAndroid Build Coastguard Worker #ifndef NETSIM_ANDROID_EMULATOR
crash_callback(const void * crash_context,size_t crash_context_size,void *)52*cf78ab8cSAndroid Build Coastguard Worker bool crash_callback(const void *crash_context, size_t crash_context_size,
53*cf78ab8cSAndroid Build Coastguard Worker                     void * /* context */) {
54*cf78ab8cSAndroid Build Coastguard Worker   std::optional<pid_t> tid;
55*cf78ab8cSAndroid Build Coastguard Worker   std::cerr << "netsimd crash_callback invoked\n";
56*cf78ab8cSAndroid Build Coastguard Worker   if (crash_context_size >=
57*cf78ab8cSAndroid Build Coastguard Worker       sizeof(google_breakpad::ExceptionHandler::CrashContext)) {
58*cf78ab8cSAndroid Build Coastguard Worker     auto *ctx =
59*cf78ab8cSAndroid Build Coastguard Worker         static_cast<const google_breakpad::ExceptionHandler::CrashContext *>(
60*cf78ab8cSAndroid Build Coastguard Worker             crash_context);
61*cf78ab8cSAndroid Build Coastguard Worker     tid = ctx->tid;
62*cf78ab8cSAndroid Build Coastguard Worker     int signal_number = ctx->siginfo.si_signo;
63*cf78ab8cSAndroid Build Coastguard Worker     std::cerr << fmt::format("Process crashed, signal: {}[{}], tid: {}\n",
64*cf78ab8cSAndroid Build Coastguard Worker                              strsignal(signal_number), signal_number, ctx->tid)
65*cf78ab8cSAndroid Build Coastguard Worker                      .c_str();
66*cf78ab8cSAndroid Build Coastguard Worker   } else {
67*cf78ab8cSAndroid Build Coastguard Worker     std::cerr << "Process crashed, signal: unknown, tid: unknown\n";
68*cf78ab8cSAndroid Build Coastguard Worker   }
69*cf78ab8cSAndroid Build Coastguard Worker   unwindstack::AndroidLocalUnwinder unwinder;
70*cf78ab8cSAndroid Build Coastguard Worker   unwindstack::AndroidUnwinderData data;
71*cf78ab8cSAndroid Build Coastguard Worker   if (!unwinder.Unwind(tid, data)) {
72*cf78ab8cSAndroid Build Coastguard Worker     std::cerr << "Unwind failed\n";
73*cf78ab8cSAndroid Build Coastguard Worker     return false;
74*cf78ab8cSAndroid Build Coastguard Worker   }
75*cf78ab8cSAndroid Build Coastguard Worker   std::cerr << "Backtrace:\n";
76*cf78ab8cSAndroid Build Coastguard Worker   for (const auto &frame : data.frames) {
77*cf78ab8cSAndroid Build Coastguard Worker     std::cerr << fmt::format("{}\n", unwinder.FormatFrame(frame)).c_str();
78*cf78ab8cSAndroid Build Coastguard Worker   }
79*cf78ab8cSAndroid Build Coastguard Worker   return true;
80*cf78ab8cSAndroid Build Coastguard Worker }
81*cf78ab8cSAndroid Build Coastguard Worker #else
82*cf78ab8cSAndroid Build Coastguard Worker // Signal handler to print backtraces and then terminate the program.
83*cf78ab8cSAndroid Build Coastguard Worker void SignalHandler(int sig) {
84*cf78ab8cSAndroid Build Coastguard Worker   size_t buffer_size = 20;  // Number of entries in that array.
85*cf78ab8cSAndroid Build Coastguard Worker   void *buffer[buffer_size];
86*cf78ab8cSAndroid Build Coastguard Worker 
87*cf78ab8cSAndroid Build Coastguard Worker   auto size = backtrace(buffer, buffer_size);
88*cf78ab8cSAndroid Build Coastguard Worker   fprintf(stderr,
89*cf78ab8cSAndroid Build Coastguard Worker           "netsim error: interrupt by signal %d. Obtained %d stack frames:\n",
90*cf78ab8cSAndroid Build Coastguard Worker           sig, size);
91*cf78ab8cSAndroid Build Coastguard Worker   backtrace_symbols_fd(buffer, size, STDERR_FILENO);
92*cf78ab8cSAndroid Build Coastguard Worker   exit(sig);
93*cf78ab8cSAndroid Build Coastguard Worker }
94*cf78ab8cSAndroid Build Coastguard Worker #endif
95*cf78ab8cSAndroid Build Coastguard Worker #endif
96*cf78ab8cSAndroid Build Coastguard Worker 
97*cf78ab8cSAndroid Build Coastguard Worker }  // namespace
98*cf78ab8cSAndroid Build Coastguard Worker 
SetUpCrashReport()99*cf78ab8cSAndroid Build Coastguard Worker void SetUpCrashReport() {
100*cf78ab8cSAndroid Build Coastguard Worker #if defined(__linux__)
101*cf78ab8cSAndroid Build Coastguard Worker #ifndef NETSIM_ANDROID_EMULATOR
102*cf78ab8cSAndroid Build Coastguard Worker   google_breakpad::MinidumpDescriptor descriptor("/tmp");
103*cf78ab8cSAndroid Build Coastguard Worker   google_breakpad::ExceptionHandler eh(descriptor, nullptr, nullptr, nullptr,
104*cf78ab8cSAndroid Build Coastguard Worker                                        true, -1);
105*cf78ab8cSAndroid Build Coastguard Worker   eh.set_crash_handler(crash_callback);
106*cf78ab8cSAndroid Build Coastguard Worker #else
107*cf78ab8cSAndroid Build Coastguard Worker   signal(SIGSEGV, SignalHandler);
108*cf78ab8cSAndroid Build Coastguard Worker #endif
109*cf78ab8cSAndroid Build Coastguard Worker #endif
110*cf78ab8cSAndroid Build Coastguard Worker }
111*cf78ab8cSAndroid Build Coastguard Worker 
112*cf78ab8cSAndroid Build Coastguard Worker }  // namespace netsim
113