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