Loading debuggerd/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ LOCAL_CPPFLAGS := \ -Wunused \ -Werror \ ifeq ($(TARGET_IS_64_BIT),true) LOCAL_CPPFLAGS += -DTARGET_IS_64_BIT endif LOCAL_SHARED_LIBRARIES := \ libbacktrace \ libcutils \ Loading debuggerd/debuggerd.cpp +107 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,14 @@ #include "tombstone.h" #include "utility.h" // If the 32 bit executable is compiled on a 64 bit system, // use the 32 bit socket name. #if defined(TARGET_IS_64_BIT) && !defined(__LP64__) #define SOCKET_NAME DEBUGGER32_SOCKET_NAME #else #define SOCKET_NAME DEBUGGER_SOCKET_NAME #endif struct debugger_request_t { debugger_action_t action; pid_t pid, tid; Loading Loading @@ -207,7 +215,7 @@ static int read_request(int fd, debugger_request_t* out_request) { return -1; } out_request->action = msg.action; out_request->action = static_cast<debugger_action_t>(msg.action); out_request->tid = msg.tid; out_request->pid = cr.pid; out_request->uid = cr.uid; Loading Loading @@ -255,6 +263,85 @@ static bool should_attach_gdb(debugger_request_t* request) { return false; } #if defined(__LP64__) static bool is32bit(pid_t tid) { char* exeline; if (asprintf(&exeline, "/proc/%d/exe", tid) == -1) { return false; } int fd = TEMP_FAILURE_RETRY(open(exeline, O_RDONLY | O_CLOEXEC)); int saved_errno = errno; free(exeline); if (fd == -1) { ALOGW("Failed to open /proc/%d/exe %s", tid, strerror(saved_errno)); return false; } char ehdr[EI_NIDENT]; ssize_t bytes = TEMP_FAILURE_RETRY(read(fd, &ehdr, sizeof(ehdr))); TEMP_FAILURE_RETRY(close(fd)); if (bytes != (ssize_t) sizeof(ehdr) || memcmp(ELFMAG, ehdr, SELFMAG) != 0) { return false; } if (ehdr[EI_CLASS] == ELFCLASS32) { return true; } return false; } static void redirect_to_32(int fd, debugger_request_t* request) { debugger_msg_t msg; memset(&msg, 0, sizeof(msg)); msg.tid = request->tid; msg.action = request->action; int sock_fd = socket_local_client(DEBUGGER32_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM | SOCK_CLOEXEC); if (sock_fd < 0) { ALOGE("Failed to connect to debuggerd32: %s", strerror(errno)); return; } if (TEMP_FAILURE_RETRY(write(sock_fd, &msg, sizeof(msg))) != (ssize_t) sizeof(msg)) { ALOGE("Failed to write request to debuggerd32 socket: %s", strerror(errno)); TEMP_FAILURE_RETRY(close(sock_fd)); return; } char ack; if (TEMP_FAILURE_RETRY(read(sock_fd, &ack, 1)) == -1) { ALOGE("Failed to read ack from debuggerd32 socket: %s", strerror(errno)); TEMP_FAILURE_RETRY(close(sock_fd)); return; } char buffer[1024]; ssize_t bytes_read; while ((bytes_read = TEMP_FAILURE_RETRY(read(sock_fd, buffer, sizeof(buffer)))) > 0) { ssize_t bytes_to_send = bytes_read; ssize_t bytes_written; do { bytes_written = TEMP_FAILURE_RETRY(write(fd, buffer + bytes_read - bytes_to_send, bytes_to_send)); if (bytes_written == -1) { if (errno == EAGAIN) { // Retry the write. continue; } ALOGE("Error while writing data to fd: %s", strerror(errno)); break; } bytes_to_send -= bytes_written; } while (bytes_written != 0 && bytes_to_send > 0); if (bytes_to_send != 0) { ALOGE("Failed to write all data to fd: read %zd, sent %zd", bytes_read, bytes_to_send); break; } } TEMP_FAILURE_RETRY(close(sock_fd)); } #endif static void handle_request(int fd) { ALOGV("handle_request(%d)\n", fd); Loading @@ -265,6 +352,24 @@ static void handle_request(int fd) { ALOGV("BOOM: pid=%d uid=%d gid=%d tid=%d\n", request.pid, request.uid, request.gid, request.tid); #if defined(__LP64__) // On 64 bit systems, requests to dump 32 bit and 64 bit tids come // to the 64 bit debuggerd. If the process is a 32 bit executable, // redirect the request to the 32 bit debuggerd. if (is32bit(request.tid)) { // Only dump backtrace and dump tombstone requests can be redirected. if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE || request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { redirect_to_32(fd, &request); } else { ALOGE("debuggerd: Not allowed to redirect action %d to 32 bit debuggerd\n", request.action); } TEMP_FAILURE_RETRY(close(fd)); return; } #endif // At this point, the thread that made the request is blocked in // a read() call. If the thread has crashed, then this gives us // time to PTRACE_ATTACH to it before it has a chance to really fault. Loading Loading @@ -428,7 +533,7 @@ static int do_server() { act.sa_flags = SA_NOCLDWAIT; sigaction(SIGCHLD, &act, 0); int s = socket_local_server(DEBUGGER_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); int s = socket_local_server(SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); if (s < 0) return 1; fcntl(s, F_SETFD, FD_CLOEXEC); Loading include/cutils/debugger.h +13 −27 Original line number Diff line number Diff line Loading @@ -17,20 +17,14 @@ #ifndef __CUTILS_DEBUGGER_H #define __CUTILS_DEBUGGER_H #include <sys/cdefs.h> #include <sys/types.h> #ifdef __cplusplus extern "C" { #endif __BEGIN_DECLS #define DEBUGGER32_SOCKET_NAME "android:debuggerd" #define DEBUGGER64_SOCKET_NAME "android:debuggerd64" #if defined(__LP64__) #define DEBUGGER_SOCKET_NAME DEBUGGER64_SOCKET_NAME #else #define DEBUGGER_SOCKET_NAME DEBUGGER32_SOCKET_NAME #endif #define DEBUGGER_SOCKET_NAME "android:debuggerd" #define DEBUGGER32_SOCKET_NAME "android:debuggerd32" #define DEBUGGER64_SOCKET_NAME DEBUGGER_SOCKET_NAME typedef enum { // dump a crash Loading @@ -41,23 +35,17 @@ typedef enum { DEBUGGER_ACTION_DUMP_BACKTRACE, } debugger_action_t; typedef struct { debugger_action_t action; // Make sure that all values have a fixed size so that this structure // is the same for 32 bit and 64 bit processes. // NOTE: Any changes to this structure must also be reflected in // bionic/linker/debugger.cpp. typedef struct __attribute__((packed)) { int32_t action; pid_t tid; uintptr_t abort_msg_address; uint64_t abort_msg_address; int32_t original_si_code; } debugger_msg_t; #if defined(__LP64__) // For a 64 bit process to contact the 32 bit debuggerd. typedef struct { debugger_action_t action; pid_t tid; uint32_t abort_msg_address; int32_t original_si_code; } debugger32_msg_t; #endif /* Dumps a process backtrace, registers, and stack to a tombstone file (requires root). * Stores the tombstone path in the provided buffer. * Returns 0 on success, -1 on error. Loading @@ -84,8 +72,6 @@ int dump_backtrace_to_file(pid_t tid, int fd); */ int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs); #ifdef __cplusplus } #endif __END_DECLS #endif /* __CUTILS_DEBUGGER_H */ libcutils/debugger.c +5 −53 Original line number Diff line number Diff line Loading @@ -29,33 +29,6 @@ #define LOG_TAG "DEBUG" #include <log/log.h> #if defined(__LP64__) #include <elf.h> static bool is32bit(pid_t tid) { char* exeline; if (asprintf(&exeline, "/proc/%d/exe", tid) == -1) { return false; } int fd = open(exeline, O_RDONLY | O_CLOEXEC); free(exeline); if (fd == -1) { return false; } char ehdr[EI_NIDENT]; ssize_t bytes = read(fd, &ehdr, sizeof(ehdr)); close(fd); if (bytes != (ssize_t) sizeof(ehdr) || memcmp(ELFMAG, ehdr, SELFMAG) != 0) { return false; } if (ehdr[EI_CLASS] == ELFCLASS32) { return true; } return false; } #endif static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) { int result = 0; if (TEMP_FAILURE_RETRY(write(sock_fd, msg_ptr, msg_len)) != (ssize_t) msg_len) { Loading @@ -72,32 +45,11 @@ static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) { static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_secs) { const char* socket_name; debugger_msg_t msg; size_t msg_len; void* msg_ptr; #if defined(__LP64__) debugger32_msg_t msg32; if (is32bit(tid)) { msg_len = sizeof(debugger32_msg_t); memset(&msg32, 0, msg_len); msg32.tid = tid; msg32.action = action; msg_ptr = &msg32; socket_name = DEBUGGER32_SOCKET_NAME; } else #endif { msg_len = sizeof(debugger_msg_t); memset(&msg, 0, msg_len); memset(&msg, 0, sizeof(msg)); msg.tid = tid; msg.action = action; msg_ptr = &msg; socket_name = DEBUGGER_SOCKET_NAME; } int sock_fd = socket_local_client(socket_name, ANDROID_SOCKET_NAMESPACE_ABSTRACT, int sock_fd = socket_local_client(DEBUGGER_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM | SOCK_CLOEXEC); if (sock_fd < 0) { return -1; Loading @@ -116,7 +68,7 @@ static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_se } } if (send_request(sock_fd, msg_ptr, msg_len) < 0) { if (send_request(sock_fd, &msg, sizeof(msg)) < 0) { TEMP_FAILURE_RETRY(close(sock_fd)); return -1; } Loading Loading
debuggerd/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ LOCAL_CPPFLAGS := \ -Wunused \ -Werror \ ifeq ($(TARGET_IS_64_BIT),true) LOCAL_CPPFLAGS += -DTARGET_IS_64_BIT endif LOCAL_SHARED_LIBRARIES := \ libbacktrace \ libcutils \ Loading
debuggerd/debuggerd.cpp +107 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,14 @@ #include "tombstone.h" #include "utility.h" // If the 32 bit executable is compiled on a 64 bit system, // use the 32 bit socket name. #if defined(TARGET_IS_64_BIT) && !defined(__LP64__) #define SOCKET_NAME DEBUGGER32_SOCKET_NAME #else #define SOCKET_NAME DEBUGGER_SOCKET_NAME #endif struct debugger_request_t { debugger_action_t action; pid_t pid, tid; Loading Loading @@ -207,7 +215,7 @@ static int read_request(int fd, debugger_request_t* out_request) { return -1; } out_request->action = msg.action; out_request->action = static_cast<debugger_action_t>(msg.action); out_request->tid = msg.tid; out_request->pid = cr.pid; out_request->uid = cr.uid; Loading Loading @@ -255,6 +263,85 @@ static bool should_attach_gdb(debugger_request_t* request) { return false; } #if defined(__LP64__) static bool is32bit(pid_t tid) { char* exeline; if (asprintf(&exeline, "/proc/%d/exe", tid) == -1) { return false; } int fd = TEMP_FAILURE_RETRY(open(exeline, O_RDONLY | O_CLOEXEC)); int saved_errno = errno; free(exeline); if (fd == -1) { ALOGW("Failed to open /proc/%d/exe %s", tid, strerror(saved_errno)); return false; } char ehdr[EI_NIDENT]; ssize_t bytes = TEMP_FAILURE_RETRY(read(fd, &ehdr, sizeof(ehdr))); TEMP_FAILURE_RETRY(close(fd)); if (bytes != (ssize_t) sizeof(ehdr) || memcmp(ELFMAG, ehdr, SELFMAG) != 0) { return false; } if (ehdr[EI_CLASS] == ELFCLASS32) { return true; } return false; } static void redirect_to_32(int fd, debugger_request_t* request) { debugger_msg_t msg; memset(&msg, 0, sizeof(msg)); msg.tid = request->tid; msg.action = request->action; int sock_fd = socket_local_client(DEBUGGER32_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM | SOCK_CLOEXEC); if (sock_fd < 0) { ALOGE("Failed to connect to debuggerd32: %s", strerror(errno)); return; } if (TEMP_FAILURE_RETRY(write(sock_fd, &msg, sizeof(msg))) != (ssize_t) sizeof(msg)) { ALOGE("Failed to write request to debuggerd32 socket: %s", strerror(errno)); TEMP_FAILURE_RETRY(close(sock_fd)); return; } char ack; if (TEMP_FAILURE_RETRY(read(sock_fd, &ack, 1)) == -1) { ALOGE("Failed to read ack from debuggerd32 socket: %s", strerror(errno)); TEMP_FAILURE_RETRY(close(sock_fd)); return; } char buffer[1024]; ssize_t bytes_read; while ((bytes_read = TEMP_FAILURE_RETRY(read(sock_fd, buffer, sizeof(buffer)))) > 0) { ssize_t bytes_to_send = bytes_read; ssize_t bytes_written; do { bytes_written = TEMP_FAILURE_RETRY(write(fd, buffer + bytes_read - bytes_to_send, bytes_to_send)); if (bytes_written == -1) { if (errno == EAGAIN) { // Retry the write. continue; } ALOGE("Error while writing data to fd: %s", strerror(errno)); break; } bytes_to_send -= bytes_written; } while (bytes_written != 0 && bytes_to_send > 0); if (bytes_to_send != 0) { ALOGE("Failed to write all data to fd: read %zd, sent %zd", bytes_read, bytes_to_send); break; } } TEMP_FAILURE_RETRY(close(sock_fd)); } #endif static void handle_request(int fd) { ALOGV("handle_request(%d)\n", fd); Loading @@ -265,6 +352,24 @@ static void handle_request(int fd) { ALOGV("BOOM: pid=%d uid=%d gid=%d tid=%d\n", request.pid, request.uid, request.gid, request.tid); #if defined(__LP64__) // On 64 bit systems, requests to dump 32 bit and 64 bit tids come // to the 64 bit debuggerd. If the process is a 32 bit executable, // redirect the request to the 32 bit debuggerd. if (is32bit(request.tid)) { // Only dump backtrace and dump tombstone requests can be redirected. if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE || request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { redirect_to_32(fd, &request); } else { ALOGE("debuggerd: Not allowed to redirect action %d to 32 bit debuggerd\n", request.action); } TEMP_FAILURE_RETRY(close(fd)); return; } #endif // At this point, the thread that made the request is blocked in // a read() call. If the thread has crashed, then this gives us // time to PTRACE_ATTACH to it before it has a chance to really fault. Loading Loading @@ -428,7 +533,7 @@ static int do_server() { act.sa_flags = SA_NOCLDWAIT; sigaction(SIGCHLD, &act, 0); int s = socket_local_server(DEBUGGER_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); int s = socket_local_server(SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); if (s < 0) return 1; fcntl(s, F_SETFD, FD_CLOEXEC); Loading
include/cutils/debugger.h +13 −27 Original line number Diff line number Diff line Loading @@ -17,20 +17,14 @@ #ifndef __CUTILS_DEBUGGER_H #define __CUTILS_DEBUGGER_H #include <sys/cdefs.h> #include <sys/types.h> #ifdef __cplusplus extern "C" { #endif __BEGIN_DECLS #define DEBUGGER32_SOCKET_NAME "android:debuggerd" #define DEBUGGER64_SOCKET_NAME "android:debuggerd64" #if defined(__LP64__) #define DEBUGGER_SOCKET_NAME DEBUGGER64_SOCKET_NAME #else #define DEBUGGER_SOCKET_NAME DEBUGGER32_SOCKET_NAME #endif #define DEBUGGER_SOCKET_NAME "android:debuggerd" #define DEBUGGER32_SOCKET_NAME "android:debuggerd32" #define DEBUGGER64_SOCKET_NAME DEBUGGER_SOCKET_NAME typedef enum { // dump a crash Loading @@ -41,23 +35,17 @@ typedef enum { DEBUGGER_ACTION_DUMP_BACKTRACE, } debugger_action_t; typedef struct { debugger_action_t action; // Make sure that all values have a fixed size so that this structure // is the same for 32 bit and 64 bit processes. // NOTE: Any changes to this structure must also be reflected in // bionic/linker/debugger.cpp. typedef struct __attribute__((packed)) { int32_t action; pid_t tid; uintptr_t abort_msg_address; uint64_t abort_msg_address; int32_t original_si_code; } debugger_msg_t; #if defined(__LP64__) // For a 64 bit process to contact the 32 bit debuggerd. typedef struct { debugger_action_t action; pid_t tid; uint32_t abort_msg_address; int32_t original_si_code; } debugger32_msg_t; #endif /* Dumps a process backtrace, registers, and stack to a tombstone file (requires root). * Stores the tombstone path in the provided buffer. * Returns 0 on success, -1 on error. Loading @@ -84,8 +72,6 @@ int dump_backtrace_to_file(pid_t tid, int fd); */ int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs); #ifdef __cplusplus } #endif __END_DECLS #endif /* __CUTILS_DEBUGGER_H */
libcutils/debugger.c +5 −53 Original line number Diff line number Diff line Loading @@ -29,33 +29,6 @@ #define LOG_TAG "DEBUG" #include <log/log.h> #if defined(__LP64__) #include <elf.h> static bool is32bit(pid_t tid) { char* exeline; if (asprintf(&exeline, "/proc/%d/exe", tid) == -1) { return false; } int fd = open(exeline, O_RDONLY | O_CLOEXEC); free(exeline); if (fd == -1) { return false; } char ehdr[EI_NIDENT]; ssize_t bytes = read(fd, &ehdr, sizeof(ehdr)); close(fd); if (bytes != (ssize_t) sizeof(ehdr) || memcmp(ELFMAG, ehdr, SELFMAG) != 0) { return false; } if (ehdr[EI_CLASS] == ELFCLASS32) { return true; } return false; } #endif static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) { int result = 0; if (TEMP_FAILURE_RETRY(write(sock_fd, msg_ptr, msg_len)) != (ssize_t) msg_len) { Loading @@ -72,32 +45,11 @@ static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) { static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_secs) { const char* socket_name; debugger_msg_t msg; size_t msg_len; void* msg_ptr; #if defined(__LP64__) debugger32_msg_t msg32; if (is32bit(tid)) { msg_len = sizeof(debugger32_msg_t); memset(&msg32, 0, msg_len); msg32.tid = tid; msg32.action = action; msg_ptr = &msg32; socket_name = DEBUGGER32_SOCKET_NAME; } else #endif { msg_len = sizeof(debugger_msg_t); memset(&msg, 0, msg_len); memset(&msg, 0, sizeof(msg)); msg.tid = tid; msg.action = action; msg_ptr = &msg; socket_name = DEBUGGER_SOCKET_NAME; } int sock_fd = socket_local_client(socket_name, ANDROID_SOCKET_NAMESPACE_ABSTRACT, int sock_fd = socket_local_client(DEBUGGER_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM | SOCK_CLOEXEC); if (sock_fd < 0) { return -1; Loading @@ -116,7 +68,7 @@ static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_se } } if (send_request(sock_fd, msg_ptr, msg_len) < 0) { if (send_request(sock_fd, &msg, sizeof(msg)) < 0) { TEMP_FAILURE_RETRY(close(sock_fd)); return -1; } Loading