aboutsummaryrefslogtreecommitdiffstats
path: root/linker
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2013-04-04 13:46:46 -0700
committerElliott Hughes <enh@google.com>2013-04-05 11:24:19 -0700
commit0d787c1fa18c6a1f29ef9840e28a68cf077be1de (patch)
tree3f8efc05d80658c9be48513238104a5de01a9951 /linker
parent014c75c78bdcad8acde8d0abb2450aa1f78e1a1f (diff)
downloadandroid_bionic-0d787c1fa18c6a1f29ef9840e28a68cf077be1de.tar.gz
android_bionic-0d787c1fa18c6a1f29ef9840e28a68cf077be1de.tar.bz2
android_bionic-0d787c1fa18c6a1f29ef9840e28a68cf077be1de.zip
Make abort messages available to debuggerd.
This adds __libc_fatal, cleans up the internal logging code a bit more, and switches suitable callers over to __libc_fatal. In addition to logging, __libc_fatal stashes the message somewhere that the debuggerd signal handler can find it before calling abort. In the debuggerd signal handler, we pass this address to debuggerd so that it can come back with ptrace to read the message and present it to the user. Bug: 8531731 Change-Id: I416ec1da38a8a1b0d0a582ccd7c8aaa681ed4a29
Diffstat (limited to 'linker')
-rw-r--r--linker/debugger.cpp30
-rw-r--r--linker/linker.cpp10
-rw-r--r--linker/linker.h1
3 files changed, 23 insertions, 18 deletions
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 6fddb1c75..a7c0591d9 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -52,8 +52,12 @@ enum debugger_action_t {
/* message sent over the socket */
struct debugger_msg_t {
- debugger_action_t action;
- pid_t tid;
+ // version 1 included:
+ debugger_action_t action;
+ pid_t tid;
+
+ // version 2 added:
+ uintptr_t abort_msg_address;
};
// see man(2) prctl, specifically the section about PR_GET_NAME
@@ -154,14 +158,14 @@ static bool haveSiginfo(int signum) {
sigemptyset(&newact.sa_mask);
if (sigaction(signum, &newact, &oldact) < 0) {
- __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed testing for SA_SIGINFO: %s",
+ __libc_format_log(ANDROID_LOG_WARN, "libc", "Failed testing for SA_SIGINFO: %s",
strerror(errno));
- return 0;
+ return false;
}
bool ret = (oldact.sa_flags & SA_SIGINFO) != 0;
if (sigaction(signum, &oldact, NULL) == -1) {
- __libc_format_log(ANDROID_LOG_FATAL, "libc", "Restore failed in test for SA_SIGINFO: %s",
+ __libc_format_log(ANDROID_LOG_WARN, "libc", "Restore failed in test for SA_SIGINFO: %s",
strerror(errno));
}
return ret;
@@ -186,19 +190,17 @@ void debuggerd_signal_handler(int n, siginfo_t* info, void*) {
int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
if (s >= 0) {
- /* debugger knows our pid from the credentials on the
- * local socket but we need to tell it our tid. It
- * is paranoid and will verify that we are giving a tid
- * that's actually in our process
- */
- int ret;
+ // debuggerd knows our pid from the credentials on the
+ // local socket but we need to tell it the tid of the crashing thread.
+ // debuggerd will be paranoid and verify that we sent a tid
+ // that's actually in our process.
debugger_msg_t msg;
msg.action = DEBUGGER_ACTION_CRASH;
msg.tid = tid;
- ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
+ msg.abort_msg_address = reinterpret_cast<uintptr_t>(gAbortMessage);
+ int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
if (ret == sizeof(msg)) {
- /* if the write failed, there is no point to read on
- * the file descriptor. */
+ // if the write failed, there is no point trying to read a response.
ret = TEMP_FAILURE_RETRY(read(s, &tid, 1));
int saved_errno = errno;
notify_gdb_of_libraries();
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 3afd31405..47c45eb0b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -105,6 +105,8 @@ static soinfo* gLdPreloads[LDPRELOAD_MAX + 1];
__LIBC_HIDDEN__ int gLdDebugVerbosity;
+__LIBC_HIDDEN__ abort_msg_t* gAbortMessage = NULL; // For debuggerd.
+
enum RelocationKind {
kRelocAbsolute = 0,
kRelocRelative,
@@ -171,8 +173,7 @@ size_t linker_get_error_buffer_size() {
*/
extern "C" void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity();
-static r_debug _r_debug = {1, NULL, &rtld_db_dlactivity,
- RT_CONSISTENT, 0};
+static r_debug _r_debug = {1, NULL, &rtld_db_dlactivity, RT_CONSISTENT, 0};
static link_map_t* r_debug_tail = 0;
static pthread_mutex_t gDebugMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -1815,8 +1816,8 @@ extern "C" Elf32_Addr __linker_init(void* raw_args) {
Elf32_Addr linker_addr = args.getauxval(AT_BASE);
- Elf32_Ehdr *elf_hdr = (Elf32_Ehdr*) linker_addr;
- Elf32_Phdr *phdr = (Elf32_Phdr*)((unsigned char*) linker_addr + elf_hdr->e_phoff);
+ Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*) linker_addr;
+ Elf32_Phdr* phdr = (Elf32_Phdr*)((unsigned char*) linker_addr + elf_hdr->e_phoff);
soinfo linker_so;
memset(&linker_so, 0, sizeof(soinfo));
@@ -1841,6 +1842,7 @@ extern "C" Elf32_Addr __linker_init(void* raw_args) {
// We have successfully fixed our own relocations. It's safe to run
// the main part of the linker now.
+ args.abort_message_ptr = &gAbortMessage;
Elf32_Addr start_address = __linker_init_post_relocation(args, linker_addr);
set_soinfo_pool_protection(PROT_READ);
diff --git a/linker/linker.h b/linker/linker.h
index 6196bec02..61d623a96 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -186,6 +186,7 @@ Elf32_Sym* dladdr_find_symbol(soinfo* si, const void* addr);
Elf32_Sym* dlsym_handle_lookup(soinfo* si, const char* name);
void debuggerd_init();
+extern "C" abort_msg_t* gAbortMessage;
extern "C" void notify_gdb_of_libraries();
char* linker_get_error_buffer();