diff options
author | 2023-12-04 15:15:59 +0000 | |
---|---|---|
committer | 2023-12-04 16:32:31 +0000 | |
commit | e274b0a8e0ea4737bf9f501a81df5e75c97972ba (patch) | |
tree | 6aa9600d6131c64c8a465c03fa2667da0107fba6 | |
parent | 04ccad00ea3b95a2477de4cc418ad55a92b5b5b4 (diff) |
Add more logging to sigchainlib to debug missing backtraces
Bug: 303039968
Bug: 314729187
Test: check that extra stack gets printed (with local modifications)
Change-Id: Idf1f5103292241073dce991826f629cfc9c6e711
-rw-r--r-- | sigchainlib/Android.bp | 1 | ||||
-rw-r--r-- | sigchainlib/log.h | 8 | ||||
-rw-r--r-- | sigchainlib/sigchain.cc | 34 | ||||
-rw-r--r-- | sigchainlib/sigchain_fake.cc | 8 |
4 files changed, 42 insertions, 9 deletions
diff --git a/sigchainlib/Android.bp b/sigchainlib/Android.bp index a9bc6326f1..6160b33972 100644 --- a/sigchainlib/Android.bp +++ b/sigchainlib/Android.bp @@ -51,6 +51,7 @@ cc_library { android: { header_libs: ["bionic_libc_platform_headers"], static_libs: ["libasync_safe"], + shared_libs: ["libunwindstack"], }, linux_bionic: { diff --git a/sigchainlib/log.h b/sigchainlib/log.h index d689930c1e..cbfc88f1c9 100644 --- a/sigchainlib/log.h +++ b/sigchainlib/log.h @@ -21,7 +21,7 @@ #include <async_safe/log.h> -#define log(...) async_safe_format_log(ANDROID_LOG_ERROR, "libsigchain", __VA_ARGS__) +#define LogError(...) async_safe_format_log(ANDROID_LOG_ERROR, "libsigchain", __VA_ARGS__) #define fatal async_safe_fatal #else @@ -29,7 +29,7 @@ #include <stdarg.h> #include <stdio.h> -static void log(const char* format, ...) { +static void LogError(const char* format, ...) { va_list ap; va_start(ap, format); vprintf(format, ap); @@ -38,7 +38,9 @@ static void log(const char* format, ...) { printf("\n"); } -#define fatal(...) log(__VA_ARGS__); abort() +#define fatal(...) \ + LogError(__VA_ARGS__); \ + abort() #endif diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index a7f73f717f..e055fd3e3c 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -16,6 +16,7 @@ #include <dlfcn.h> #include <errno.h> +#include <inttypes.h> #include <pthread.h> #include <signal.h> #include <stdio.h> @@ -24,6 +25,7 @@ #if defined(__BIONIC__) #include <bionic/macros.h> +#include <unwindstack/AndroidUnwinder.h> #endif #include <algorithm> @@ -96,6 +98,28 @@ static int sigorset(SigsetType* dest, SigsetType* left, SigsetType* right) { return 0; } +void LogStack() { +#if defined(__BIONIC__) + unwindstack::AndroidLocalUnwinder unwinder; + unwindstack::AndroidUnwinderData data; + if (!unwinder.Unwind(data)) { + LogError("Failed to get callstack."); + return; + } + data.DemangleFunctionNames(); + for (const unwindstack::FrameData& frame : data.frames) { + auto& map = frame.map_info; + LogError(" #%02zu pc %08" PRIx64 " %s (%s+%" PRIu64 ") (BuildId: %s)", + frame.num, + frame.rel_pc, + map != nullptr ? map->name().c_str() : "???", + frame.function_name.c_str(), + frame.function_offset, + map != nullptr ? map->GetPrintableBuildID().c_str() : "???"); + } +#endif +} + namespace art { static decltype(&sigaction) linked_sigaction; @@ -490,7 +514,8 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { // the crash will have no way to know our ucontext, and thus no way to dump the original crash // stack (since we're on an alternate stack.) Let's remove our handler and return. Then the // pre-crash state is restored, the crash happens again, and the next handler gets a chance. - log("reverting to SIG_DFL handler for signal %d, ucontext %p", signo, ucontext); + LogError("reverting to SIG_DFL handler for signal %d, ucontext %p", signo, ucontext); + LogStack(); struct sigaction dfl = {}; dfl.sa_handler = SIG_DFL; linked_sigaction(signo, &dfl, nullptr); @@ -519,6 +544,11 @@ static int __sigaction(int signal, const SigactionType* new_action, return -1; } + if (signal == SIGSEGV && new_action != nullptr && new_action->sa_handler == SIG_DFL) { + LogError("Setting SIGSEGV to SIG_DFL"); + LogStack(); + } + if (chains[signal].IsClaimed()) { SigactionType saved_action = chains[signal].GetAction<SigactionType>(); if (new_action != nullptr) { @@ -672,7 +702,7 @@ extern "C" void EnsureFrontOfChain(int signal) { // If the sigactions don't match then we put the current action on the chain and make ourself as // the main action. if (current_action.sa_sigaction != SignalChain::Handler) { - log("Warning: Unexpected sigaction action found %p\n", current_action.sa_sigaction); + LogError("Warning: Unexpected sigaction action found %p\n", current_action.sa_sigaction); chains[signal].Register(signal); } } diff --git a/sigchainlib/sigchain_fake.cc b/sigchainlib/sigchain_fake.cc index 0e62eebf8c..06f6569e05 100644 --- a/sigchainlib/sigchain_fake.cc +++ b/sigchainlib/sigchain_fake.cc @@ -28,24 +28,24 @@ namespace art { extern "C" void EnsureFrontOfChain([[maybe_unused]] int signal) { - log("EnsureFrontOfChain is not exported by the main executable."); + LogError("EnsureFrontOfChain is not exported by the main executable."); abort(); } extern "C" void AddSpecialSignalHandlerFn([[maybe_unused]] int signal, [[maybe_unused]] SigchainAction* sa) { - log("SetSpecialSignalHandlerFn is not exported by the main executable."); + LogError("SetSpecialSignalHandlerFn is not exported by the main executable."); abort(); } extern "C" void RemoveSpecialSignalHandlerFn([[maybe_unused]] int signal, [[maybe_unused]] bool (*fn)(int, siginfo_t*, void*)) { - log("SetSpecialSignalHandlerFn is not exported by the main executable."); + LogError("SetSpecialSignalHandlerFn is not exported by the main executable."); abort(); } extern "C" void SkipAddSignalHandler([[maybe_unused]] bool value) { - log("SkipAddSignalHandler is not exported by the main executable."); + LogError("SkipAddSignalHandler is not exported by the main executable."); abort(); } |