diff options
author | Pavel Chupin <pavel.v.chupin@intel.com> | 2013-11-21 23:17:20 +0400 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2014-01-30 17:15:24 -0800 |
commit | c6c194ced095df5e777b8fa24527ebd29c8fef54 (patch) | |
tree | e8c2872d11d30743d38f915b90ce394d2773ccf2 | |
parent | e97dad0d95ae1305686bf4294029da947fc2dcf2 (diff) | |
download | system_core-c6c194ced095df5e777b8fa24527ebd29c8fef54.zip system_core-c6c194ced095df5e777b8fa24527ebd29c8fef54.tar.gz system_core-c6c194ced095df5e777b8fa24527ebd29c8fef54.tar.bz2 |
LP64: Enable debuggerd/libbacktrace/libunwind.
Change-Id: I2e432839f86c33c2adbaac8cc12ca8961956044b
Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
-rw-r--r-- | debuggerd/Android.mk | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | debuggerd/tombstone.cpp | 45 | ||||
-rw-r--r-- | debuggerd/utility.cpp | 47 | ||||
-rw-r--r-- | debuggerd/utility.h | 11 | ||||
-rw-r--r-- | debuggerd/x86_64/crashglue.S | 15 | ||||
-rwxr-xr-x | debuggerd/x86_64/machine.cpp | 51 | ||||
-rw-r--r-- | include/backtrace/Backtrace.h | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | libbacktrace/Android.mk | 2 | ||||
-rw-r--r-- | libbacktrace/BacktraceImpl.cpp | 18 | ||||
-rwxr-xr-x[-rw-r--r--] | libbacktrace/BacktraceImpl.h | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | libbacktrace/UnwindCurrent.cpp | 3 |
11 files changed, 129 insertions, 83 deletions
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 422a86a..8c1c3d8 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -1,6 +1,6 @@ # Copyright 2005 The Android Open Source Project -ifneq ($(filter arm mips x86,$(TARGET_ARCH)),) +ifneq ($(filter arm mips x86 x86_64,$(TARGET_ARCH)),) LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -19,6 +19,7 @@ LOCAL_CFLAGS := \ -Wall \ -Wno-array-bounds \ -Werror \ + -Wno-unused-parameter \ LOCAL_MODULE := debuggerd diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index 7bda5c5..b66890e 100644..100755 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -179,9 +179,9 @@ static void dump_fault_addr(log_t* log, pid_t tid, int sig) { if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){ _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno)); } else if (signal_has_address(sig)) { - _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %0*" PRIxPTR "\n", + _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %" PRIPTR "\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code), - sizeof(uintptr_t)*2, reinterpret_cast<uintptr_t>(si.si_addr)); + reinterpret_cast<uintptr_t>(si.si_addr)); } else { _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code)); @@ -226,7 +226,7 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, int scope_flags) static void dump_stack_segment( Backtrace* backtrace, log_t* log, int scope_flags, uintptr_t* sp, size_t words, int label) { for (size_t i = 0; i < words; i++) { - uint32_t stack_content; + word_t stack_content; if (!backtrace->ReadWord(*sp, &stack_content)) { break; } @@ -243,32 +243,32 @@ static void dump_stack_segment( if (!func_name.empty()) { if (!i && label >= 0) { if (offset) { - _LOG(log, scope_flags, " #%02d %08x %08x %s (%s+%u)\n", + _LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s (%s+%" PRIxPTR "u)\n", label, *sp, stack_content, map_name, func_name.c_str(), offset); } else { - _LOG(log, scope_flags, " #%02d %08x %08x %s (%s)\n", + _LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s (%s)\n", label, *sp, stack_content, map_name, func_name.c_str()); } } else { if (offset) { - _LOG(log, scope_flags, " %08x %08x %s (%s+%u)\n", + _LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s (%s+%" PRIxPTR "u)\n", *sp, stack_content, map_name, func_name.c_str(), offset); } else { - _LOG(log, scope_flags, " %08x %08x %s (%s)\n", + _LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s (%s)\n", *sp, stack_content, map_name, func_name.c_str()); } } } else { if (!i && label >= 0) { - _LOG(log, scope_flags, " #%02d %08x %08x %s\n", + _LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s\n", label, *sp, stack_content, map_name); } else { - _LOG(log, scope_flags, " %08x %08x %s\n", + _LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s\n", *sp, stack_content, map_name); } } - *sp += sizeof(uint32_t); + *sp += sizeof(word_t); } } @@ -291,7 +291,7 @@ static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) { scope_flags |= SCOPE_SENSITIVE; // Dump a few words before the first frame. - uintptr_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(uint32_t); + word_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(word_t); dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, -1); // Dump a few words from all successive frames. @@ -311,7 +311,7 @@ static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) { _LOG(log, scope_flags, " ........ ........\n"); } } else { - size_t words = frame->stack_size / sizeof(uint32_t); + size_t words = frame->stack_size / sizeof(word_t); if (words == 0) { words = 1; } else if (words > STACK_WORDS) { @@ -334,7 +334,7 @@ static void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log, int scope static void dump_map(log_t* log, const backtrace_map_t* map, const char* what, int scope_flags) { if (map != NULL) { - _LOG(log, scope_flags, " %08x-%08x %c%c%c %s\n", map->start, map->end, + _LOG(log, scope_flags, " %" PRIPTR "-%" PRIPTR " %c%c%c %s\n", map->start, map->end, (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-', (map->flags & PROT_EXEC) ? 'x' : '-', map->name.c_str()); } else { @@ -573,24 +573,15 @@ static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t addre memset(msg, 0, sizeof(msg)); char* p = &msg[0]; while (p < &msg[sizeof(msg)]) { - uint32_t data; + word_t data; + size_t len = sizeof(word_t); if (!backtrace->ReadWord(address, &data)) { break; } - address += sizeof(uint32_t); + address += sizeof(word_t); - if ((*p++ = (data >> 0) & 0xff) == 0) { - break; - } - if ((*p++ = (data >> 8) & 0xff) == 0) { - break; - } - if ((*p++ = (data >> 16) & 0xff) == 0) { - break; - } - if ((*p++ = (data >> 24) & 0xff) == 0) { - break; - } + while (len > 0 && (*p++ = (data >> (sizeof(word_t) - len) * 8) & 0xff) != 0) + len--; } msg[sizeof(msg) - 1] = '\0'; diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp index 100324a..9b20914 100644 --- a/debuggerd/utility.cpp +++ b/debuggerd/utility.cpp @@ -14,19 +14,17 @@ * limitations under the License. */ -#include <stddef.h> -#include <stdio.h> -#include <string.h> +#include "utility.h" + #include <errno.h> -#include <unistd.h> #include <signal.h> -#include <log/logd.h> +#include <string.h> +#include <unistd.h> #include <sys/ptrace.h> #include <sys/wait.h> -#include <arpa/inet.h> -#include <assert.h> -#include "utility.h" +#include <backtrace/Backtrace.h> +#include <log/logd.h> const int sleep_time_usec = 50000; // 0.05 seconds const int max_total_sleep_usec = 10000000; // 10 seconds @@ -34,7 +32,7 @@ const int max_total_sleep_usec = 10000000; // 10 seconds static int write_to_am(int fd, const char* buf, int len) { int to_write = len; while (to_write > 0) { - int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) ); + int written = TEMP_FAILURE_RETRY(write(fd, buf + len - to_write, to_write)); if (written < 0) { // hard failure LOG("AM write failure (%d / %s)\n", errno, strerror(errno)); @@ -46,34 +44,28 @@ static int write_to_am(int fd, const char* buf, int len) { } void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) { - char buf[512]; - bool want_tfd_write; - bool want_log_write; - bool want_amfd_write; - int len = 0; + bool want_tfd_write = log && log->tfd >= 0; + bool want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet); + bool want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0; + char buf[512]; va_list ap; va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); - // where is the information going to go? - want_tfd_write = log && log->tfd >= 0; - want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet); - want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0; - - // if we're going to need the literal string, generate it once here - if (want_tfd_write || want_amfd_write) { - vsnprintf(buf, sizeof(buf), fmt, ap); - len = strlen(buf); + size_t len = strlen(buf); + if (len <= 0) { + return; } if (want_tfd_write) { - write(log->tfd, buf, len); + TEMP_FAILURE_RETRY(write(log->tfd, buf, len)); } if (want_log_write) { - // whatever goes to logcat also goes to the Activity Manager - __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap); - if (want_amfd_write && len > 0) { + __android_log_write(ANDROID_LOG_INFO, "DEBUG", buf); + if (want_amfd_write) { int written = write_to_am(log->amfd, buf, len); if (written <= 0) { // timeout or other failure on write; stop informing the activity manager @@ -81,7 +73,6 @@ void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) { } } } - va_end(ap); } int wait_for_signal(pid_t tid, int* total_sleep_time_usec) { diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 232b7bc..0f88605 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -18,9 +18,8 @@ #ifndef _DEBUGGERD_UTILITY_H #define _DEBUGGERD_UTILITY_H -#include <inttypes.h> #include <stdbool.h> -#include <stddef.h> +#include <sys/types.h> typedef struct { /* tombstone file descriptor */ @@ -61,14 +60,6 @@ void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) #define XLOG2(fmt...) do {} while(0) #endif -#if __LP64__ -#define PRIPTR "016" PRIxPTR -typedef uint64_t word_t; -#else -#define PRIPTR "08" PRIxPTR -typedef uint32_t word_t; -#endif - int wait_for_signal(pid_t tid, int* total_sleep_time_usec); void wait_for_stop(pid_t tid, int* total_sleep_time_usec); diff --git a/debuggerd/x86_64/crashglue.S b/debuggerd/x86_64/crashglue.S new file mode 100644 index 0000000..4d2a5c0 --- /dev/null +++ b/debuggerd/x86_64/crashglue.S @@ -0,0 +1,15 @@ +.globl crash1 +.globl crashnostack + +crash1: + movl $0xa5a50000, %eax + movl $0xa5a50001, %ebx + movl $0xa5a50002, %ecx + + movl $0, %edx + jmp *%rdx + + +crashnostack: + movl $0, %ebp + jmp *%rbp diff --git a/debuggerd/x86_64/machine.cpp b/debuggerd/x86_64/machine.cpp new file mode 100755 index 0000000..406851a --- /dev/null +++ b/debuggerd/x86_64/machine.cpp @@ -0,0 +1,51 @@ +/* +** Copyright 2013, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include <stddef.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/user.h> + +#include "../utility.h" +#include "../machine.h" + +void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) { +} + +void dump_registers(log_t* log, pid_t tid, int scope_flags) { + struct user_regs_struct r; + if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) { + _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno)); + return; + } + _LOG(log, scope_flags, " rax %016lx rbx %016lx rcx %016lx rdx %016lx\n", + r.rax, r.rbx, r.rcx, r.rdx); + _LOG(log, scope_flags, " rsi %016lx rdi %016lx\n", + r.rsi, r.rdi); + _LOG(log, scope_flags, " r8 %016lx r9 %016lx r10 %016lx r11 %016lx\n", + r.r8, r.r9, r.r10, r.r11); + _LOG(log, scope_flags, " r12 %016lx r13 %016lx r14 %016lx r15 %016lx\n", + r.r12, r.r13, r.r14, r.r15); + _LOG(log, scope_flags, " cs %016lx ss %016lx\n", + r.cs, r.ss); + _LOG(log, scope_flags, " rip %016lx rbp %016lx rsp %016lx eflags %016lx\n", + r.rip, r.rbp, r.rsp, r.eflags); +} diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h index bd4134c..3c3a482 100644 --- a/include/backtrace/Backtrace.h +++ b/include/backtrace/Backtrace.h @@ -17,6 +17,7 @@ #ifndef _BACKTRACE_BACKTRACE_H #define _BACKTRACE_BACKTRACE_H +#include <inttypes.h> #include <stdint.h> #include <string> @@ -25,6 +26,14 @@ #include <backtrace/backtrace_constants.h> #include <backtrace/BacktraceMap.h> +#if __LP64__ +#define PRIPTR "016" PRIxPTR +typedef uint64_t word_t; +#else +#define PRIPTR "08" PRIxPTR +typedef uint32_t word_t; +#endif + struct backtrace_frame_data_t { size_t num; // The current fame number. uintptr_t pc; // The absolute pc. @@ -65,7 +74,7 @@ public: virtual const backtrace_map_t* FindMap(uintptr_t pc); // Read the data at a specific address. - virtual bool ReadWord(uintptr_t ptr, uint32_t* out_value) = 0; + virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0; // Create a string representing the formatted line of backtrace information // for a single frame. @@ -96,7 +105,7 @@ public: protected: Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map); - virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value); + virtual bool VerifyReadWordArgs(uintptr_t ptr, word_t* out_value); bool BuildMap(); diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk index 17a807d..ee90f28 100644..100755 --- a/libbacktrace/Android.mk +++ b/libbacktrace/Android.mk @@ -23,7 +23,7 @@ common_shared_libs := \ liblog \ # To enable using libunwind on each arch, add it to this list. -libunwind_architectures := arm arm64 x86 +libunwind_architectures := arm arm64 x86 x86_64 ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),$(libunwind_architectures))) diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp index 8027d86..855810e 100644 --- a/libbacktrace/BacktraceImpl.cpp +++ b/libbacktrace/BacktraceImpl.cpp @@ -21,8 +21,6 @@ #include <sys/types.h> #include <unistd.h> -#include <inttypes.h> - #include <string> #include <backtrace/Backtrace.h> @@ -81,10 +79,10 @@ std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { return func_name; } -bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) { - if (ptr & 3) { +bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) { + if (ptr & (sizeof(word_t)-1)) { BACK_LOGW("invalid pointer %p", (void*)ptr); - *out_value = (uint32_t)-1; + *out_value = (word_t)-1; return false; } return true; @@ -142,18 +140,18 @@ BacktraceCurrent::BacktraceCurrent( BacktraceCurrent::~BacktraceCurrent() { } -bool BacktraceCurrent::ReadWord(uintptr_t ptr, uint32_t* out_value) { +bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { if (!VerifyReadWordArgs(ptr, out_value)) { return false; } const backtrace_map_t* map = FindMap(ptr); if (map && map->flags & PROT_READ) { - *out_value = *reinterpret_cast<uint32_t*>(ptr); + *out_value = *reinterpret_cast<word_t*>(ptr); return true; } else { BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); - *out_value = static_cast<uint32_t>(-1); + *out_value = static_cast<word_t>(-1); return false; } } @@ -170,7 +168,7 @@ BacktracePtrace::BacktracePtrace( BacktracePtrace::~BacktracePtrace() { } -bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) { +bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) { if (!VerifyReadWordArgs(ptr, out_value)) { return false; } @@ -183,7 +181,7 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) { // To disambiguate -1 from a valid result, we clear errno beforehand. errno = 0; *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL); - if (*out_value == static_cast<uint32_t>(-1) && errno) { + if (*out_value == static_cast<word_t>(-1) && errno) { BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s", reinterpret_cast<void*>(ptr), Tid(), strerror(errno)); return false; diff --git a/libbacktrace/BacktraceImpl.h b/libbacktrace/BacktraceImpl.h index af014d5..48dd11c 100644..100755 --- a/libbacktrace/BacktraceImpl.h +++ b/libbacktrace/BacktraceImpl.h @@ -61,7 +61,7 @@ public: BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map); virtual ~BacktraceCurrent(); - bool ReadWord(uintptr_t ptr, uint32_t* out_value); + bool ReadWord(uintptr_t ptr, word_t* out_value); }; class BacktracePtrace : public Backtrace { @@ -69,7 +69,7 @@ public: BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map); virtual ~BacktracePtrace(); - bool ReadWord(uintptr_t ptr, uint32_t* out_value); + bool ReadWord(uintptr_t ptr, word_t* out_value); }; Backtrace* CreateCurrentObj(BacktraceMap* map); diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp index 461ed02..81e69bb 100644..100755 --- a/libbacktrace/UnwindCurrent.cpp +++ b/libbacktrace/UnwindCurrent.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "libbacktrace" +#include <sys/ucontext.h> #include <sys/types.h> #include <backtrace/Backtrace.h> @@ -27,8 +28,6 @@ #include "UnwindCurrent.h" #include "UnwindMap.h" -#include <ucontext.h> - //------------------------------------------------------------------------- // UnwindCurrent functions. //------------------------------------------------------------------------- |