diff options
Diffstat (limited to 'debuggerd/handler/debuggerd_handler.cpp')
-rw-r--r-- | debuggerd/handler/debuggerd_handler.cpp | 35 |
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. |