diff options
Diffstat (limited to 'debuggerd')
-rw-r--r-- | debuggerd/Android.mk | 4 | ||||
-rw-r--r-- | debuggerd/debuggerd.cpp | 109 |
2 files changed, 111 insertions, 2 deletions
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 0cf2818..fbaac39 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -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 \ diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 318b224..039b8ec 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -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; @@ -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; @@ -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); @@ -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. @@ -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); |