summaryrefslogtreecommitdiff
path: root/debuggerd/handler/debuggerd_handler.cpp
diff options
context:
space:
mode:
authorBill Peckham <bpeckham@google.com>2018-09-24 16:43:13 -0700
committerBill Peckham <bpeckham@google.com>2018-09-24 16:43:13 -0700
commit40e42bfff84f1b73e53913cfadf6504ec5adf31e (patch)
tree92dafb087b7ea519290d0a343358cc526648f051 /debuggerd/handler/debuggerd_handler.cpp
parent76da659f67a0363e75756bbfb66bb7e8c90cf054 (diff)
parentc1d7b74441779acaf1b5855a1c07d56822b498a4 (diff)
Merge QP1A.180918.001
Change-Id: I6e221d7a92b6ecb92bb8364757522d4906b86877
Diffstat (limited to 'debuggerd/handler/debuggerd_handler.cpp')
-rw-r--r--debuggerd/handler/debuggerd_handler.cpp35
1 files changed, 25 insertions, 10 deletions
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 98594efdf..94dada952 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -58,6 +58,8 @@
#include "dump_type.h"
#include "protocol.h"
+#include "handler/fallback.h"
+
using android::base::Pipe;
// We muck with our fds in a 'thread' that doesn't share the same fd table.
@@ -457,14 +459,14 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
info = nullptr;
}
- struct siginfo si = {};
+ struct siginfo dummy_info = {};
if (!info) {
- memset(&si, 0, sizeof(si));
- si.si_signo = signal_number;
- si.si_code = SI_USER;
- si.si_pid = __getpid();
- si.si_uid = getuid();
- info = &si;
+ memset(&dummy_info, 0, sizeof(dummy_info));
+ dummy_info.si_signo = signal_number;
+ dummy_info.si_code = SI_USER;
+ dummy_info.si_pid = __getpid();
+ dummy_info.si_uid = getuid();
+ info = &dummy_info;
} else if (info->si_code >= 0 || info->si_code == SI_TKILL) {
// rt_tgsigqueueinfo(2)'s documentation appears to be incorrect on kernels
// that contain commit 66dd34a (3.9+). The manpage claims to only allow
@@ -473,8 +475,20 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
}
void* abort_message = nullptr;
- if (signal_number != DEBUGGER_SIGNAL && g_callbacks.get_abort_message) {
- abort_message = g_callbacks.get_abort_message();
+ uintptr_t si_val = reinterpret_cast<uintptr_t>(info->si_ptr);
+ if (signal_number == DEBUGGER_SIGNAL) {
+ if (info->si_code == SI_QUEUE && info->si_pid == __getpid()) {
+ // Allow for the abort message to be explicitly specified via the sigqueue value.
+ // Keep the bottom bit intact for representing whether we want a backtrace or a tombstone.
+ if (si_val != kDebuggerdFallbackSivalUintptrRequestDump) {
+ abort_message = reinterpret_cast<void*>(si_val & ~1);
+ info->si_ptr = reinterpret_cast<void*>(si_val & 1);
+ }
+ }
+ } else {
+ if (g_callbacks.get_abort_message) {
+ abort_message = g_callbacks.get_abort_message();
+ }
}
// If sival_int is ~0, it means that the fallback handler has been called
@@ -482,7 +496,8 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c
// of a specific thread. It is possible that the prctl call might return 1,
// then return 0 in subsequent calls, so check the sival_int to determine if
// the fallback handler should be called first.
- if (info->si_value.sival_int == ~0 || prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
+ if (si_val == kDebuggerdFallbackSivalUintptrRequestDump ||
+ prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
// This check might be racy if another thread sets NO_NEW_PRIVS, but this should be unlikely,
// you can only set NO_NEW_PRIVS to 1, and the effect should be at worst a single missing
// ANR trace.