Log signal info at time of receipt
When a fatal signal is received, we now write a message to the log
that looks like this:
F/libc ( 1540): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1)
This is useful for debugging fatal signals that turn out not to be
fatal. This also changes the signal reset from SIG_IGN to SIG_DFL,
so that future non-fatal fatal signals are fatal.
The code that blocked SIGUSR1 to avoid being interrupted by the GC
has been removed.
Also, fix minor issues in format_buffer().
Bug 5035703
Change-Id: I8940af47297b5dcf3cf33537e3483ca5334ed565
diff --git a/linker/debugger.c b/linker/debugger.c
index abb383c..648dc78 100644
--- a/linker/debugger.c
+++ b/linker/debugger.c
@@ -87,13 +87,49 @@
return s;
}
-void debugger_signal_handler(int n)
+#include "linker_format.h"
+#include <../libc/private/logd.h>
+
+/*
+ * Writes a summary of the signal to the log file.
+ *
+ * We could be here as a result of native heap corruption, or while a
+ * mutex is being held, so we don't want to use any libc functions that
+ * could allocate memory or hold a lock.
+ */
+static void logSignalSummary(int signum, const siginfo_t* info)
+{
+ char buffer[128];
+
+ char* signame;
+ switch (signum) {
+ case SIGILL: signame = "SIGILL"; break;
+ case SIGABRT: signame = "SIGABRT"; break;
+ case SIGBUS: signame = "SIGBUS"; break;
+ case SIGFPE: signame = "SIGFPE"; break;
+ case SIGSEGV: signame = "SIGSEGV"; break;
+ case SIGSTKFLT: signame = "SIGSTKFLT"; break;
+ case SIGPIPE: signame = "SIGPIPE"; break;
+ default: signame = "???"; break;
+ }
+
+ format_buffer(buffer, sizeof(buffer),
+ "Fatal signal %d (%s) at 0x%08x (code=%d)",
+ signum, signame, info->si_addr, info->si_code);
+
+ __libc_android_log_write(ANDROID_LOG_FATAL, "libc", buffer);
+}
+
+/*
+ * Catches fatal signals so we can ask debuggerd to ptrace us before
+ * we crash.
+ */
+void debugger_signal_handler(int n, siginfo_t* info, void* unused)
{
unsigned tid;
int s;
- /* avoid picking up GC interrupts */
- signal(SIGUSR1, SIG_IGN);
+ logSignalSummary(n, info);
tid = gettid();
s = socket_abstract_client("android:debuggerd", SOCK_STREAM);
@@ -117,16 +153,22 @@
}
/* remove our net so we fault for real when we return */
- signal(n, SIG_IGN);
+ signal(n, SIG_DFL);
}
void debugger_init()
{
- signal(SIGILL, debugger_signal_handler);
- signal(SIGABRT, debugger_signal_handler);
- signal(SIGBUS, debugger_signal_handler);
- signal(SIGFPE, debugger_signal_handler);
- signal(SIGSEGV, debugger_signal_handler);
- signal(SIGSTKFLT, debugger_signal_handler);
- signal(SIGPIPE, debugger_signal_handler);
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+ act.sa_sigaction = debugger_signal_handler;
+ act.sa_flags = SA_RESTART | SA_SIGINFO;
+ sigemptyset(&act.sa_mask);
+
+ sigaction(SIGILL, &act, NULL);
+ sigaction(SIGABRT, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+ sigaction(SIGFPE, &act, NULL);
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGSTKFLT, &act, NULL);
+ sigaction(SIGPIPE, &act, NULL);
}