11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved.
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *  * Redistributions of source code must retain the above copyright
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    the documentation and/or other materials provided with the
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    distribution.
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2918a206c81d9743481e364384affd43306911283dElliott Hughes#include "linker.h"
30ed70f6a2a03c3d172d3770039e65dc262d5b4075Dimitry Ivanov#include "linker_gdb_support.h"
3118a206c81d9743481e364384affd43306911283dElliott Hughes
3284114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughes#include <errno.h>
3317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes#include <inttypes.h>
348ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris#include <pthread.h>
3584114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughes#include <signal.h>
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
388ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris#include <string.h>
3984114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughes#include <sys/mman.h>
403df3e672f51580525452c2eeb4d35633d4dba873Marco Nelissen#include <sys/prctl.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h>
4206abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao#include <sys/syscall.h>
438bff9a31aa13ff83ccaedd54ebda96770e6cf910David 'Digit' Turner#include <sys/un.h>
4484114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughes#include <unistd.h>
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4618a206c81d9743481e364384affd43306911283dElliott Hughesextern "C" int tgkill(int tgid, int tid, int sig);
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
48151da681000c07da3c24cd30a3279b1ca017f452Christopher Ferris// Crash actions have to be sent to the proper debuggerd.
49151da681000c07da3c24cd30a3279b1ca017f452Christopher Ferris// On 64 bit systems, the 32 bit debuggerd is named differently.
50151da681000c07da3c24cd30a3279b1ca017f452Christopher Ferris#if defined(TARGET_IS_64_BIT) && !defined(__LP64__)
51151da681000c07da3c24cd30a3279b1ca017f452Christopher Ferris#define DEBUGGER_SOCKET_NAME "android:debuggerd32"
52f858bd1c6eec7eb6bbfc8844e0de096be011e99aElliott Hughes#else
53b7630f018abc83261acf78e8cf9a88c1df72f7f5Jeff Brown#define DEBUGGER_SOCKET_NAME "android:debuggerd"
54f858bd1c6eec7eb6bbfc8844e0de096be011e99aElliott Hughes#endif
55b7630f018abc83261acf78e8cf9a88c1df72f7f5Jeff Brown
5618a206c81d9743481e364384affd43306911283dElliott Hughesenum debugger_action_t {
5717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // dump a crash
5817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  DEBUGGER_ACTION_CRASH,
5917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // dump a tombstone file
6017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  DEBUGGER_ACTION_DUMP_TOMBSTONE,
6117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // dump a backtrace only back to the socket
6217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  DEBUGGER_ACTION_DUMP_BACKTRACE,
6318a206c81d9743481e364384affd43306911283dElliott Hughes};
64b7630f018abc83261acf78e8cf9a88c1df72f7f5Jeff Brown
6506abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao// Message sent over the socket.
6606abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao// NOTE: Any changes to this structure must also be reflected in
6706abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao//       system/core/include/cutils/debugger.h.
68151da681000c07da3c24cd30a3279b1ca017f452Christopher Ferrisstruct __attribute__((packed)) debugger_msg_t {
69151da681000c07da3c24cd30a3279b1ca017f452Christopher Ferris  int32_t action;
700d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes  pid_t tid;
71151da681000c07da3c24cd30a3279b1ca017f452Christopher Ferris  uint64_t abort_msg_address;
72b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  int32_t original_si_code;
7318a206c81d9743481e364384affd43306911283dElliott Hughes};
747934a799e1041db9cff9753f4d87d7361f644450David 'Digit' Turner
753df3e672f51580525452c2eeb4d35633d4dba873Marco Nelissen// see man(2) prctl, specifically the section about PR_GET_NAME
763df3e672f51580525452c2eeb4d35633d4dba873Marco Nelissen#define MAX_TASK_NAME_LEN (16)
778bff9a31aa13ff83ccaedd54ebda96770e6cf910David 'Digit' Turner
7818a206c81d9743481e364384affd43306911283dElliott Hughesstatic int socket_abstract_client(const char* name, int type) {
7917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  sockaddr_un addr;
8017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
8117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // Test with length +1 for the *initial* '\0'.
8217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  size_t namelen = strlen(name);
8317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  if ((namelen + 1) > sizeof(addr.sun_path)) {
8417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    errno = EINVAL;
8517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    return -1;
8617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
8717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
8817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // This is used for abstract socket namespace, we need
8917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // an initial '\0' at the start of the Unix socket path.
9017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  //
9117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // Note: The path in this case is *not* supposed to be
9217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // '\0'-terminated. ("man 7 unix" for the gory details.)
9317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  memset(&addr, 0, sizeof(addr));
9417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  addr.sun_family = AF_LOCAL;
9517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  addr.sun_path[0] = 0;
9617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  memcpy(addr.sun_path + 1, name, namelen);
9717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
9817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
9917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
10017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  int s = socket(AF_LOCAL, type, 0);
10117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  if (s == -1) {
10217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    return -1;
10317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
10417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
10517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  int rc = TEMP_FAILURE_RETRY(connect(s, reinterpret_cast<sockaddr*>(&addr), alen));
10617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  if (rc == -1) {
10717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    close(s);
10817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    return -1;
10917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
11017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
11117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  return s;
1128bff9a31aa13ff83ccaedd54ebda96770e6cf910David 'Digit' Turner}
1138bff9a31aa13ff83ccaedd54ebda96770e6cf910David 'Digit' Turner
114ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden/*
1151db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden * Writes a summary of the signal to the log file.  We do this so that, if
1161db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden * for some reason we're not able to contact debuggerd, there is still some
1171db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden * indication of the failure in the log.
118ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden *
119ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden * We could be here as a result of native heap corruption, or while a
120ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden * mutex is being held, so we don't want to use any libc functions that
121ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden * could allocate memory or hold a lock.
122ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden */
12384114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughesstatic void log_signal_summary(int signum, const siginfo_t* info) {
12417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  const char* signal_name = "???";
12517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  bool has_address = false;
12617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  switch (signum) {
12717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    case SIGABRT:
12817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      signal_name = "SIGABRT";
12917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      break;
13017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    case SIGBUS:
13117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      signal_name = "SIGBUS";
13217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      has_address = true;
13317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      break;
13417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    case SIGFPE:
13517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      signal_name = "SIGFPE";
13617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      has_address = true;
13717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      break;
13862e35755eb09caa6cf4892150fb87a6347afef6eElliott Hughes    case SIGILL:
13962e35755eb09caa6cf4892150fb87a6347afef6eElliott Hughes      signal_name = "SIGILL";
14062e35755eb09caa6cf4892150fb87a6347afef6eElliott Hughes      has_address = true;
14162e35755eb09caa6cf4892150fb87a6347afef6eElliott Hughes      break;
14217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    case SIGSEGV:
14317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      signal_name = "SIGSEGV";
14417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      has_address = true;
14517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      break;
146d7daacb46372132ae3f0121647074936c304b572Raghu Gandham#if defined(SIGSTKFLT)
14717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    case SIGSTKFLT:
14817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      signal_name = "SIGSTKFLT";
14917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      break;
150d7daacb46372132ae3f0121647074936c304b572Raghu Gandham#endif
15162e35755eb09caa6cf4892150fb87a6347afef6eElliott Hughes    case SIGTRAP:
15262e35755eb09caa6cf4892150fb87a6347afef6eElliott Hughes      signal_name = "SIGTRAP";
15317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes      break;
15417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
15517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
15617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination
1571649e7ee5b9bb4122be67903d55c4c8cc0549bbaDmitriy Ivanov  if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name), 0, 0, 0) != 0) {
15817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    strcpy(thread_name, "<name unknown>");
15917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  } else {
16017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    // short names are null terminated by prctl, but the man page
16117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    // implies that 16 byte names are not.
16217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    thread_name[MAX_TASK_NAME_LEN] = 0;
16317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
16417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
165851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  // "info" will be null if the siginfo_t information was not available.
16617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // Many signals don't have an address or a code.
16717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  char code_desc[32]; // ", code -6"
16817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  char addr_desc[32]; // ", fault addr 0x1234"
16917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  addr_desc[0] = code_desc[0] = 0;
170851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  if (info != nullptr) {
17117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    // For a rethrown signal, this si_code will be right and the one debuggerd shows will
17217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    // always be SI_TKILL.
173052fa3a34c07b9b361c30565f029dd543da14e30Christopher Ferris    __libc_format_buffer(code_desc, sizeof(code_desc), ", code %d", info->si_code);
17417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    if (has_address) {
175052fa3a34c07b9b361c30565f029dd543da14e30Christopher Ferris      __libc_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
1761db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden    }
17717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
17817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  __libc_format_log(ANDROID_LOG_FATAL, "libc",
17917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes                    "Fatal signal %d (%s)%s%s in tid %d (%s)",
18017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes                    signum, signal_name, code_desc, addr_desc, gettid(), thread_name);
181ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden}
182ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden
183ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden/*
1841db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden * Returns true if the handler for signal "signum" has SA_SIGINFO set.
1851db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden */
18684114c8dd5b17efecf7988f263ce431208d7be5aElliott Hughesstatic bool have_siginfo(int signum) {
18717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  struct sigaction old_action, new_action;
18817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
18917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  memset(&new_action, 0, sizeof(new_action));
19017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  new_action.sa_handler = SIG_DFL;
19117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  new_action.sa_flags = SA_RESTART;
19217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  sigemptyset(&new_action.sa_mask);
19317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
19417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  if (sigaction(signum, &new_action, &old_action) < 0) {
19517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    __libc_format_log(ANDROID_LOG_WARN, "libc", "Failed testing for SA_SIGINFO: %s",
19617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes                      strerror(errno));
19717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    return false;
19817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
19917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  bool result = (old_action.sa_flags & SA_SIGINFO) != 0;
20017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
201851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  if (sigaction(signum, &old_action, nullptr) == -1) {
20217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes    __libc_format_log(ANDROID_LOG_WARN, "libc", "Restore failed in test for SA_SIGINFO: %s",
20317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes                      strerror(errno));
20417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
20517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  return result;
2061db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden}
2071db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden
208b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughesstatic void send_debuggerd_packet(siginfo_t* info) {
2098ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris  // Mutex to prevent multiple crashing threads from trying to talk
2108ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris  // to debuggerd at the same time.
2118ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris  static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
2128ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris  int ret = pthread_mutex_trylock(&crash_mutex);
2138ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris  if (ret != 0) {
2148ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris    if (ret == EBUSY) {
2158ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris      __libc_format_log(ANDROID_LOG_INFO, "libc",
21620d89cb5b0d5eb7546a8fe8da44bbd91564dbddaDmitriy Ivanov          "Another thread contacted debuggerd first; not contacting debuggerd.");
2178ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris      // This will never complete since the lock is never released.
2188ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris      pthread_mutex_lock(&crash_mutex);
2198ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris    } else {
2208ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris      __libc_format_log(ANDROID_LOG_INFO, "libc",
2218ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris                        "pthread_mutex_trylock failed: %s", strerror(ret));
2228ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris    }
2238ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris    return;
2248ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris  }
2258ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris
2260dc39f9952c5e3a3121ea77357bb264ef0f8ded7Elliott Hughes  int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM | SOCK_CLOEXEC);
227b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  if (s == -1) {
228b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
229b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes                      strerror(errno));
230b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    return;
231b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  }
232b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes
233b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  // debuggerd knows our pid from the credentials on the
234b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  // local socket but we need to tell it the tid of the crashing thread.
235b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  // debuggerd will be paranoid and verify that we sent a tid
236b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  // that's actually in our process.
237b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  debugger_msg_t msg;
238b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  msg.action = DEBUGGER_ACTION_CRASH;
239b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  msg.tid = gettid();
2401728b2396591853345507a063ed6075dfd251706Elliott Hughes  msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_abort_message);
241851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  msg.original_si_code = (info != nullptr) ? info->si_code : 0;
2428ea53fa87e63dac824c274216d84d7eda973805cChristopher Ferris  ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
243b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  if (ret == sizeof(msg)) {
244b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    char debuggerd_ack;
245b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
246b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    int saved_errno = errno;
247b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    notify_gdb_of_libraries();
248b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    errno = saved_errno;
249b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  } else {
250b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    // read or write failed -- broken connection?
251b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
252b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes                      strerror(errno));
253b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  }
254b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes
255b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  close(s);
256b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes}
257b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes
2581db6f2db499490e125a92e2c859a6dc3bef81d72Andy McFadden/*
259ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden * Catches fatal signals so we can ask debuggerd to ptrace us before
260ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden * we crash.
261ec92af8fe5d28c74f3505932135b1b8f3fbaad00Andy McFadden */
262b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughesstatic void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
26317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // It's possible somebody cleared the SA_SIGINFO flag, which would mean
26417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // our "info" arg holds an undefined value.
26517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  if (!have_siginfo(signal_number)) {
266851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov    info = nullptr;
26717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
26817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
26917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  log_signal_summary(signal_number, info);
27017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
271b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes  send_debuggerd_packet(info);
27217e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
27306abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  // We need to return from the signal handler so that debuggerd can dump the
27406abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  // thread that crashed, but returning here does not guarantee that the signal
27506abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  // will be thrown again, even for SIGSEGV and friends, since the signal could
27606abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  // have been sent manually. Resend the signal with rt_tgsigqueueinfo(2) to
27706abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  // preserve the SA_SIGINFO contents.
27817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  signal(signal_number, SIG_DFL);
27917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
28006abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  struct siginfo si;
28106abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  if (!info) {
28206abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    memset(&si, 0, sizeof(si));
28306abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    si.si_code = SI_USER;
28406abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    si.si_pid = getpid();
28506abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    si.si_uid = getuid();
28606abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    info = &si;
28706abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  } else if (info->si_code >= 0 || info->si_code == SI_TKILL) {
28806abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    // rt_tgsigqueueinfo(2)'s documentation appears to be incorrect on kernels
28906abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    // that contain commit 66dd34a (3.9+). The manpage claims to only allow
29006abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    // negative si_code values that are not SI_TKILL, but 66dd34a changed the
29106abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    // check to allow all si_code values in calls coming from inside the house.
29206abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  }
29306abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao
29406abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), signal_number, info);
29506abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao  if (rc != 0) {
29606abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    __libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to resend signal during crash: %s",
29706abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao                      strerror(errno));
29806abceff0f9434d5a5150527bf6bdbad13f897e0Josh Gao    _exit(0);
29917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  }
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
302b7e289ed028ee73fda4c044e07d3ec6f783a0ef4Elliott Hughes__LIBC_HIDDEN__ void debuggerd_init() {
30317e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  struct sigaction action;
30417e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  memset(&action, 0, sizeof(action));
30517e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  sigemptyset(&action.sa_mask);
30617e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  action.sa_sigaction = debuggerd_signal_handler;
30717e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  action.sa_flags = SA_RESTART | SA_SIGINFO;
30817e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
30917e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  // Use the alternate signal stack if available so we can catch stack overflows.
31017e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes  action.sa_flags |= SA_ONSTACK;
31117e6a98b48c4f228adb37c8d37bbf71dd2a1c513Elliott Hughes
312851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  sigaction(SIGABRT, &action, nullptr);
313851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  sigaction(SIGBUS, &action, nullptr);
314851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  sigaction(SIGFPE, &action, nullptr);
315851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  sigaction(SIGILL, &action, nullptr);
316851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  sigaction(SIGSEGV, &action, nullptr);
317d7daacb46372132ae3f0121647074936c304b572Raghu Gandham#if defined(SIGSTKFLT)
318851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  sigaction(SIGSTKFLT, &action, nullptr);
319d7daacb46372132ae3f0121647074936c304b572Raghu Gandham#endif
320851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  sigaction(SIGTRAP, &action, nullptr);
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
322