diff options
Diffstat (limited to 'linker/debugger.cpp')
-rw-r--r-- | linker/debugger.cpp | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/linker/debugger.cpp b/linker/debugger.cpp index ac466a5..357fbdc 100644 --- a/linker/debugger.cpp +++ b/linker/debugger.cpp @@ -30,9 +30,11 @@ #include <errno.h> #include <inttypes.h> +#include <pthread.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/mman.h> #include <sys/prctl.h> #include <sys/socket.h> @@ -41,8 +43,10 @@ extern "C" int tgkill(int tgid, int tid, int sig); -#if __LP64__ -#define DEBUGGER_SOCKET_NAME "android:debuggerd64" +// Crash actions have to be sent to the proper debuggerd. +// On 64 bit systems, the 32 bit debuggerd is named differently. +#if defined(TARGET_IS_64_BIT) && !defined(__LP64__) +#define DEBUGGER_SOCKET_NAME "android:debuggerd32" #else #define DEBUGGER_SOCKET_NAME "android:debuggerd" #endif @@ -57,15 +61,10 @@ enum debugger_action_t { }; /* message sent over the socket */ -struct debugger_msg_t { - // version 1 included: - debugger_action_t action; +struct __attribute__((packed)) debugger_msg_t { + int32_t action; pid_t tid; - - // version 2 added: - uintptr_t abort_msg_address; - - // version 3 added: + uint64_t abort_msg_address; int32_t original_si_code; }; @@ -154,7 +153,7 @@ static void log_signal_summary(int signum, const siginfo_t* info) { } char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination - if (prctl(PR_GET_NAME, (unsigned long)thread_name, 0, 0, 0) != 0) { + if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name), 0, 0, 0) != 0) { strcpy(thread_name, "<name unknown>"); } else { // short names are null terminated by prctl, but the man page @@ -215,6 +214,23 @@ static void send_debuggerd_packet(siginfo_t* info) { return; } + // Mutex to prevent multiple crashing threads from trying to talk + // to debuggerd at the same time. + static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER; + int ret = pthread_mutex_trylock(&crash_mutex); + if (ret != 0) { + if (ret == EBUSY) { + __libc_format_log(ANDROID_LOG_INFO, "libc", + "Another thread contacted debuggerd first; not contacting debuggerd."); + // This will never complete since the lock is never released. + pthread_mutex_lock(&crash_mutex); + } else { + __libc_format_log(ANDROID_LOG_INFO, "libc", + "pthread_mutex_trylock failed: %s", strerror(ret)); + } + return; + } + int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM | SOCK_CLOEXEC); if (s == -1) { __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s", @@ -231,7 +247,7 @@ static void send_debuggerd_packet(siginfo_t* info) { msg.tid = gettid(); msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_abort_message); msg.original_si_code = (info != nullptr) ? info->si_code : 0; - int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg))); + ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg))); if (ret == sizeof(msg)) { char debuggerd_ack; ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1)); |