summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Srbecky <dsrbecky@google.com> 2023-12-04 15:15:59 +0000
committer David Srbecky <dsrbecky@google.com> 2023-12-04 16:32:31 +0000
commite274b0a8e0ea4737bf9f501a81df5e75c97972ba (patch)
tree6aa9600d6131c64c8a465c03fa2667da0107fba6
parent04ccad00ea3b95a2477de4cc418ad55a92b5b5b4 (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.bp1
-rw-r--r--sigchainlib/log.h8
-rw-r--r--sigchainlib/sigchain.cc34
-rw-r--r--sigchainlib/sigchain_fake.cc8
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();
}