diff options
31 files changed, 1050 insertions, 953 deletions
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 422a86a..e0a2d96 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -1,7 +1,5 @@ # Copyright 2005 The Android Open Source Project -ifneq ($(filter arm mips x86,$(TARGET_ARCH)),) - LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -19,8 +17,13 @@ LOCAL_CFLAGS := \ -Wall \ -Wno-array-bounds \ -Werror \ + -Wno-unused-parameter \ -LOCAL_MODULE := debuggerd +ifeq ($(TARGET_IS_64_BIT),true) + LOCAL_MODULE := debuggerd64 +else + LOCAL_MODULE := debuggerd +endif ifeq ($(ARCH_ARM_HAVE_VFP),true) LOCAL_CFLAGS += -DWITH_VFP @@ -59,12 +62,10 @@ ifeq ($(ARCH_ARM_HAVE_VFP_D32),true) LOCAL_CFLAGS += -DWITH_VFP_D32 endif # ARCH_ARM_HAVE_VFP_D32 -LOCAL_SRC_FILES := vfp-crasher.c vfp.S +LOCAL_SRC_FILES := vfp-crasher.c $(TARGET_ARCH)/vfp.S LOCAL_MODULE := vfp-crasher LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libcutils liblog libc include $(BUILD_EXECUTABLE) endif # ARCH_ARM_HAVE_VFP == true - -endif # arm or x86 in TARGET_ARCH diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp index 3fba6db..fd2f69b 100644 --- a/debuggerd/arm/machine.cpp +++ b/debuggerd/arm/machine.cpp @@ -38,65 +38,6 @@ #endif #endif -static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) { - char code_buffer[64]; // actual 8+1+((8+1)*4) + 1 == 45 - char ascii_buffer[32]; // actual 16 + 1 == 17 - uintptr_t p, end; - - p = addr & ~3; - p -= 32; - if (p > addr) { - // catch underflow - p = 0; - } - // Dump more memory content for the crashing thread. - end = p + 256; - // catch overflow; 'end - p' has to be multiples of 16 - while (end < p) - end -= 16; - - // Dump the code around PC as: - // addr contents ascii - // 00008d34 ef000000 e8bd0090 e1b00000 512fff1e ............../Q - // 00008d44 ea00b1f9 e92d0090 e3a070fc ef000000 ......-..p...... - while (p < end) { - char* asc_out = ascii_buffer; - - sprintf(code_buffer, "%08x ", p); - - int i; - for (i = 0; i < 4; i++) { - // If we see (data == -1 && errno != 0), we know that the ptrace - // call failed, probably because we're dumping memory in an - // unmapped or inaccessible page. I don't know if there's - // value in making that explicit in the output -- it likely - // just complicates parsing and clarifies nothing for the - // enlightened reader. - long data = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(p), NULL); - sprintf(code_buffer + strlen(code_buffer), "%08lx ", data); - - // Enable the following code blob to dump ASCII values -#if 0 - int j; - for (j = 0; j < 4; j++) { - // Our isprint() allows high-ASCII characters that display - // differently (often badly) in different viewers, so we - // just use a simpler test. - char val = (data >> (j*8)) & 0xff; - if (val >= 0x20 && val < 0x7f) { - *asc_out++ = val; - } else { - *asc_out++ = '.'; - } - } -#endif - p += 4; - } - *asc_out = '\0'; - _LOG(log, scope_flags, " %s %s\n", code_buffer, ascii_buffer); - } -} - // If configured to do so, dump memory around *all* registers // for the crashing thread. void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) { diff --git a/debuggerd/vfp.S b/debuggerd/arm/vfp.S index 9744f6f..9744f6f 100644 --- a/debuggerd/vfp.S +++ b/debuggerd/arm/vfp.S diff --git a/debuggerd/arm64/crashglue.S b/debuggerd/arm64/crashglue.S new file mode 100644 index 0000000..b06b67c --- /dev/null +++ b/debuggerd/arm64/crashglue.S @@ -0,0 +1,47 @@ +.globl crash1 +.type crash1, %function +.globl crashnostack +.type crashnostack, %function + +crash1: + ldr x0, =0xa5a50000 + ldr x1, =0xa5a50001 + ldr x2, =0xa5a50002 + ldr x3, =0xa5a50003 + ldr x4, =0xa5a50004 + ldr x5, =0xa5a50005 + ldr x6, =0xa5a50006 + ldr x7, =0xa5a50007 + ldr x8, =0xa5a50008 + ldr x9, =0xa5a50009 + ldr x10, =0xa5a50010 + ldr x11, =0xa5a50011 + ldr x12, =0xa5a50012 + ldr x13, =0xa5a50013 + ldr x14, =0xa5a50014 + ldr x15, =0xa5a50015 + ldr x16, =0xa5a50016 + ldr x17, =0xa5a50017 + ldr x18, =0xa5a50018 + ldr x19, =0xa5a50019 + ldr x20, =0xa5a50020 + ldr x21, =0xa5a50021 + ldr x22, =0xa5a50022 + ldr x23, =0xa5a50023 + ldr x24, =0xa5a50024 + ldr x25, =0xa5a50025 + ldr x26, =0xa5a50026 + ldr x27, =0xa5a50027 + ldr x28, =0xa5a50028 + ldr x29, =0xa5a50029 + + mov x30, xzr + ldr x30, [x30] + b . + + +crashnostack: + mov x0, xzr + add sp, x0, xzr + ldr x0, [x0] + b . diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp new file mode 100644 index 0000000..7159228 --- /dev/null +++ b/debuggerd/arm64/machine.cpp @@ -0,0 +1,123 @@ +/* + * + * Copyright 2014, 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 <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/user.h> +#include <sys/uio.h> +#include <linux/elf.h> + +#include "../utility.h" +#include "../machine.h" + +/* enable to dump memory pointed to by every register */ +#define DUMP_MEMORY_FOR_ALL_REGISTERS 1 + +/* + * If configured to do so, dump memory around *all* registers + * for the crashing thread. + */ +void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) { + struct user_pt_regs regs; + struct iovec io; + io.iov_base = ®s; + io.iov_len = sizeof(regs); + + if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, &io) == -1) { + _LOG(log, scope_flags, "%s: ptrace failed to get registers: %s\n", + __func__, strerror(errno)); + return; + } + + if (IS_AT_FAULT(scope_flags) && DUMP_MEMORY_FOR_ALL_REGISTERS) { + for (int reg = 0; reg < 31; reg++) { + uintptr_t addr = regs.regs[reg]; + + /* + * Don't bother if it looks like a small int or ~= null, or if + * it's in the kernel area. + */ + if (addr < 4096 || addr >= (1UL<<63)) { + continue; + } + + _LOG(log, scope_flags | SCOPE_SENSITIVE, "\nmemory near x%d:\n", reg); + dump_memory(log, tid, addr, scope_flags | SCOPE_SENSITIVE); + } + } + + _LOG(log, scope_flags, "\ncode around pc:\n"); + dump_memory(log, tid, (uintptr_t)regs.pc, scope_flags); + + if (regs.pc != regs.sp) { + _LOG(log, scope_flags, "\ncode around sp:\n"); + dump_memory(log, tid, (uintptr_t)regs.sp, scope_flags); + } +} + +void dump_registers(log_t* log, pid_t tid, int scope_flags) +{ + struct user_pt_regs r; + struct iovec io; + io.iov_base = &r; + io.iov_len = sizeof(r); + + bool only_in_tombstone = !IS_AT_FAULT(scope_flags); + + if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRSTATUS, (void*) &io) == -1) { + _LOG(log, scope_flags, "ptrace error: %s\n", strerror(errno)); + return; + } + + for (int i = 0; i < 28; i += 4) { + _LOG(log, scope_flags, " x%-2d %016lx x%-2d %016lx x%-2d %016lx x%-2d %016lx\n", + i, (uint64_t)r.regs[i], + i+1, (uint64_t)r.regs[i+1], + i+2, (uint64_t)r.regs[i+2], + i+3, (uint64_t)r.regs[i+3]); + } + + _LOG(log, scope_flags, " x28 %016lx x29 %016lx x30 %016lx\n", + (uint64_t)r.regs[28], (uint64_t)r.regs[29], (uint64_t)r.regs[30]); + + _LOG(log, scope_flags, " sp %016lx pc %016lx\n", + (uint64_t)r.sp, (uint64_t)r.pc); + + + struct user_fpsimd_state f; + io.iov_base = &f; + io.iov_len = sizeof(f); + + if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRFPREG, (void*) &io) == -1) { + _LOG(log, scope_flags, "ptrace error: %s\n", strerror(errno)); + return; + } + + for (int i = 0; i < 32; i += 4) { + _LOG(log, scope_flags, " v%-2d %016lx v%-2d %016lx v%-2d %016lx v%-2d %016lx\n", + i, (uint64_t)f.vregs[i], + i+1, (uint64_t)f.vregs[i+1], + i+2, (uint64_t)f.vregs[i+2], + i+3, (uint64_t)f.vregs[i+3]); + } +} diff --git a/debuggerd/arm64/vfp.S b/debuggerd/arm64/vfp.S new file mode 100644 index 0000000..bf12c22 --- /dev/null +++ b/debuggerd/arm64/vfp.S @@ -0,0 +1,42 @@ + .text + .align 2 + .global crash + .type crash, %function +crash: + fmov d0, XZR + fmov d1, 1.0 + fmov d2, 2.0 + fmov d3, 3.0 + fmov d4, 4.0 + fmov d5, 5.0 + fmov d6, 6.0 + fmov d7, 7.0 + fmov d8, 8.0 + fmov d9, 9.0 + fmov d10, 10.0 + fmov d11, 11.0 + fmov d12, 12.0 + fmov d13, 13.0 + fmov d14, 14.0 + fmov d15, 15.0 + fmov d16, 16.0 + fmov d17, 17.0 + fmov d18, 18.0 + fmov d19, 19.0 + fmov d20, 20.0 + fmov d21, 21.0 + fmov d22, 22.0 + fmov d23, 23.0 + fmov d24, 24.0 + fmov d25, 25.0 + fmov d26, 26.0 + fmov d27, 27.0 + fmov d28, 28.0 + fmov d29, 29.0 + fmov d30, 30.0 + fmov d31, 31.0 + + mov x0, xzr + str x0, [x0] + br x30 + diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c index 5ecb1a5..0033948 100644 --- a/debuggerd/crasher.c +++ b/debuggerd/crasher.c @@ -23,19 +23,6 @@ void crash1(void); void crashnostack(void); static int do_action(const char* arg); -static void debuggerd_connect() -{ - char tmp[1]; - int s; - sprintf(tmp, "%d", gettid()); - s = socket_local_client("android:debuggerd", - ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); - if(s >= 0) { - read(s, tmp, 1); - close(s); - } -} - static void maybeabort() { if(time(0) != 42) { abort(); diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index de8ba9d..c39aaf6 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -205,7 +205,8 @@ static int read_request(int fd, debugger_request_t* out_request) { return -1; } if (status == sizeof(debugger_msg_t)) { - XLOG("crash request of size %d abort_msg_address=%#08x\n", status, msg.abort_msg_address); + XLOG("crash request of size %d abort_msg_address=0x%" PRIPTR "\n", + status, msg.abort_msg_address); } else { LOG("invalid crash request of size %d (from pid=%d uid=%d)\n", status, cr.pid, cr.uid); return -1; diff --git a/debuggerd/mips/machine.cpp b/debuggerd/mips/machine.cpp index d1a7f2d..7b4e29e 100644 --- a/debuggerd/mips/machine.cpp +++ b/debuggerd/mips/machine.cpp @@ -34,61 +34,6 @@ #define R(x) (static_cast<unsigned int>(x)) -static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) { - char code_buffer[64]; // actual 8+1+((8+1)*4) + 1 == 45 - char ascii_buffer[32]; // actual 16 + 1 == 17 - uintptr_t p, end; - - p = addr & ~3; - p -= 32; - if (p > addr) { - // catch underflow - p = 0; - } - end = p + 80; - // catch overflow; 'end - p' has to be multiples of 16 - while (end < p) - end -= 16; - - // Dump the code around PC as: - // addr contents ascii - // 00008d34 ef000000 e8bd0090 e1b00000 512fff1e ............../Q - // 00008d44 ea00b1f9 e92d0090 e3a070fc ef000000 ......-..p...... - while (p < end) { - char* asc_out = ascii_buffer; - - sprintf(code_buffer, "%08x ", p); - - int i; - for (i = 0; i < 4; i++) { - // If we see (data == -1 && errno != 0), we know that the ptrace - // call failed, probably because we're dumping memory in an - // unmapped or inaccessible page. I don't know if there's - // value in making that explicit in the output -- it likely - // just complicates parsing and clarifies nothing for the - // enlightened reader. - long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL); - sprintf(code_buffer + strlen(code_buffer), "%08lx ", data); - - int j; - for (j = 0; j < 4; j++) { - // Our isprint() allows high-ASCII characters that display - // differently (often badly) in different viewers, so we - // just use a simpler test. - char val = (data >> (j*8)) & 0xff; - if (val >= 0x20 && val < 0x7f) { - *asc_out++ = val; - } else { - *asc_out++ = '.'; - } - } - p += 4; - } - *asc_out = '\0'; - _LOG(log, scope_flags, " %s %s\n", code_buffer, ascii_buffer); - } -} - // If configured to do so, dump memory around *all* registers // for the crashing thread. void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) { diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index 11e9af5..c630020 100644..100755 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -14,18 +14,20 @@ * limitations under the License. */ +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <signal.h> #include <stddef.h> +#include <stdio.h> #include <stdlib.h> -#include <signal.h> #include <string.h> -#include <stdio.h> -#include <fcntl.h> -#include <errno.h> -#include <dirent.h> #include <time.h> #include <sys/ptrace.h> +#include <sys/socket.h> #include <sys/stat.h> -#include <inttypes.h> +#include <sys/un.h> #include <private/android_filesystem_config.h> @@ -36,9 +38,6 @@ #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> -#include <sys/socket.h> -#include <linux/un.h> - #include <selinux/android.h> #include <UniquePtr.h> @@ -51,6 +50,7 @@ #define MAX_TOMBSTONES 10 #define TOMBSTONE_DIR "/data/tombstones" +#define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d") // Must match the path defined in NativeCrashListener.java #define NCRASH_SOCKET_PATH "/data/system/ndebugsocket" @@ -60,7 +60,6 @@ typeof(y) __dummy2; \ (void)(&__dummy1 == &__dummy2); } - static bool signal_has_address(int sig) { switch (sig) { case SIGILL: @@ -180,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)); @@ -227,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; } @@ -244,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+%" PRIuPTR ")\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+%" PRIuPTR ")\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); } } @@ -292,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. @@ -312,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) { @@ -335,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 { @@ -361,7 +360,7 @@ static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid, int scope return; } - _LOG(log, scope_flags, "\nmemory map around fault addr %" PRIxPTR ":\n", + _LOG(log, scope_flags, "\nmemory map around fault addr %" PRIPTR ":\n", reinterpret_cast<uintptr_t>(si.si_addr)); // Search for a match, or for a hole where the match would be. The list @@ -574,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'; @@ -663,7 +653,11 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a // // Returns the path of the tombstone file, allocated using malloc(). Caller must free() it. static char* find_and_open_tombstone(int* fd) { +#ifdef __aarch64__ + long mtime = LONG_MAX; +#else unsigned long mtime = ULONG_MAX; +#endif struct stat sb; // XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought @@ -675,7 +669,7 @@ static char* find_and_open_tombstone(int* fd) { char path[128]; int oldest = 0; for (int i = 0; i < MAX_TOMBSTONES; i++) { - snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i); + snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, i); if (!stat(path, &sb)) { if (sb.st_mtime < mtime) { @@ -696,7 +690,7 @@ static char* find_and_open_tombstone(int* fd) { } // we didn't find an available file, so we clobber the oldest one - snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest); + snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, oldest); *fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (*fd < 0) { LOG("failed to open tombstone file '%s': %s\n", path, strerror(errno)); @@ -739,8 +733,13 @@ static int activity_manager_connect() { char* engrave_tombstone( pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address, bool dump_sibling_threads, bool quiet, bool* detach_failed, int* total_sleep_time_usec) { - mkdir(TOMBSTONE_DIR, 0755); - chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM); + if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) { + LOG("failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno)); + } + + if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) { + LOG("failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno)); + } if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) { *detach_failed = false; diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp index 35f061e..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) { @@ -127,3 +118,77 @@ void wait_for_stop(pid_t tid, int* total_sleep_time_usec) { *total_sleep_time_usec += sleep_time_usec; } } + +#if defined (__mips__) +#define DUMP_MEMORY_AS_ASCII 1 +#else +#define DUMP_MEMORY_AS_ASCII 0 +#endif + +void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) { + char code_buffer[64]; + char ascii_buffer[32]; + uintptr_t p, end; + + p = addr & ~(sizeof(long) - 1); + /* Dump 32 bytes before addr */ + p -= 32; + if (p > addr) { + /* catch underflow */ + p = 0; + } + /* Dump 256 bytes */ + end = p + 256; + /* catch overflow; 'end - p' has to be multiples of 16 */ + while (end < p) { + end -= 16; + } + + /* Dump the code around PC as: + * addr contents ascii + * 0000000000008d34 ef000000e8bd0090 e1b00000512fff1e ............../Q + * 0000000000008d44 ea00b1f9e92d0090 e3a070fcef000000 ......-..p...... + * On 32-bit machines, there are still 16 bytes per line but addresses and + * words are of course presented differently. + */ + while (p < end) { + char* asc_out = ascii_buffer; + + int len = snprintf(code_buffer, sizeof(code_buffer), "%" PRIPTR " ", p); + + for (size_t i = 0; i < 16/sizeof(long); i++) { + long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL); + if (data == -1 && errno != 0) { + // ptrace failed, probably because we're dumping memory in an + // unmapped or inaccessible page. +#ifdef __LP64__ + len += sprintf(code_buffer + len, "---------------- "); +#else + len += sprintf(code_buffer + len, "-------- "); +#endif + } else { + len += sprintf(code_buffer + len, "%" PRIPTR " ", + static_cast<uintptr_t>(data)); + } + +#if DUMP_MEMORY_AS_ASCII + for (size_t j = 0; j < sizeof(long); j++) { + /* + * Our isprint() allows high-ASCII characters that display + * differently (often badly) in different viewers, so we + * just use a simpler test. + */ + char val = (data >> (j*8)) & 0xff; + if (val >= 0x20 && val < 0x7f) { + *asc_out++ = val; + } else { + *asc_out++ = '.'; + } + } +#endif + p += sizeof(long); + } + *asc_out = '\0'; + _LOG(log, scope_flags, " %s %s\n", code_buffer, ascii_buffer); + } +} diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 1f006ed..0f88605 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -18,8 +18,8 @@ #ifndef _DEBUGGERD_UTILITY_H #define _DEBUGGERD_UTILITY_H -#include <stddef.h> #include <stdbool.h> +#include <sys/types.h> typedef struct { /* tombstone file descriptor */ @@ -63,4 +63,6 @@ void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) int wait_for_signal(pid_t tid, int* total_sleep_time_usec); void wait_for_stop(pid_t tid, int* total_sleep_time_usec); +void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags); + #endif // _DEBUGGERD_UTILITY_H 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/fs_mgr/Android.mk b/fs_mgr/Android.mk index 790598a..165ebd4 100644 --- a/fs_mgr/Android.mk +++ b/fs_mgr/Android.mk @@ -3,7 +3,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c +LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c fs_mgr_fstab.c LOCAL_C_INCLUDES := $(LOCAL_PATH)/include diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index 24ce806..4c2f247 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -54,55 +54,6 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) -struct flag_list { - const char *name; - unsigned flag; -}; - -static struct flag_list mount_flags[] = { - { "noatime", MS_NOATIME }, - { "noexec", MS_NOEXEC }, - { "nosuid", MS_NOSUID }, - { "nodev", MS_NODEV }, - { "nodiratime", MS_NODIRATIME }, - { "ro", MS_RDONLY }, - { "rw", 0 }, - { "remount", MS_REMOUNT }, - { "bind", MS_BIND }, - { "rec", MS_REC }, - { "unbindable", MS_UNBINDABLE }, - { "private", MS_PRIVATE }, - { "slave", MS_SLAVE }, - { "shared", MS_SHARED }, - { "defaults", 0 }, - { 0, 0 }, -}; - -static struct flag_list fs_mgr_flags[] = { - { "wait", MF_WAIT }, - { "check", MF_CHECK }, - { "encryptable=",MF_CRYPT }, - { "nonremovable",MF_NONREMOVABLE }, - { "voldmanaged=",MF_VOLDMANAGED}, - { "length=", MF_LENGTH }, - { "recoveryonly",MF_RECOVERYONLY }, - { "swapprio=", MF_SWAPPRIO }, - { "zramsize=", MF_ZRAMSIZE }, - { "verify", MF_VERIFY }, - { "noemulatedsd", MF_NOEMULATEDSD }, - { "defaults", 0 }, - { 0, 0 }, -}; - -struct fs_mgr_flag_values { - char *key_loc; - long long part_length; - char *label; - int partnum; - int swap_prio; - unsigned int zram_size; -}; - /* * gettime() - returns the time in seconds of the system's monotonic clock or * zero on error. @@ -133,269 +84,6 @@ static int wait_for_file(const char *filename, int timeout) return ret; } -static int parse_flags(char *flags, struct flag_list *fl, - struct fs_mgr_flag_values *flag_vals, - char *fs_options, int fs_options_len) -{ - int f = 0; - int i; - char *p; - char *savep; - - /* initialize flag values. If we find a relevant flag, we'll - * update the value */ - if (flag_vals) { - memset(flag_vals, 0, sizeof(*flag_vals)); - flag_vals->partnum = -1; - flag_vals->swap_prio = -1; /* negative means it wasn't specified. */ - } - - /* initialize fs_options to the null string */ - if (fs_options && (fs_options_len > 0)) { - fs_options[0] = '\0'; - } - - p = strtok_r(flags, ",", &savep); - while (p) { - /* Look for the flag "p" in the flag list "fl" - * If not found, the loop exits with fl[i].name being null. - */ - for (i = 0; fl[i].name; i++) { - if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { - f |= fl[i].flag; - if ((fl[i].flag == MF_CRYPT) && flag_vals) { - /* The encryptable flag is followed by an = and the - * location of the keys. Get it and return it. - */ - flag_vals->key_loc = strdup(strchr(p, '=') + 1); - } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { - /* The length flag is followed by an = and the - * size of the partition. Get it and return it. - */ - flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0); - } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) { - /* The voldmanaged flag is followed by an = and the - * label, a colon and the partition number or the - * word "auto", e.g. - * voldmanaged=sdcard:3 - * Get and return them. - */ - char *label_start; - char *label_end; - char *part_start; - - label_start = strchr(p, '=') + 1; - label_end = strchr(p, ':'); - if (label_end) { - flag_vals->label = strndup(label_start, - (int) (label_end - label_start)); - part_start = strchr(p, ':') + 1; - if (!strcmp(part_start, "auto")) { - flag_vals->partnum = -1; - } else { - flag_vals->partnum = strtol(part_start, NULL, 0); - } - } else { - ERROR("Warning: voldmanaged= flag malformed\n"); - } - } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) { - flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0); - } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) { - flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0); - } - break; - } - } - - if (!fl[i].name) { - if (fs_options) { - /* It's not a known flag, so it must be a filesystem specific - * option. Add it to fs_options if it was passed in. - */ - strlcat(fs_options, p, fs_options_len); - strlcat(fs_options, ",", fs_options_len); - } else { - /* fs_options was not passed in, so if the flag is unknown - * it's an error. - */ - ERROR("Warning: unknown flag %s\n", p); - } - } - p = strtok_r(NULL, ",", &savep); - } - -out: - if (fs_options && fs_options[0]) { - /* remove the last trailing comma from the list of options */ - fs_options[strlen(fs_options) - 1] = '\0'; - } - - return f; -} - -struct fstab *fs_mgr_read_fstab(const char *fstab_path) -{ - FILE *fstab_file; - int cnt, entries; - ssize_t len; - size_t alloc_len = 0; - char *line = NULL; - const char *delim = " \t"; - char *save_ptr, *p; - struct fstab *fstab = NULL; - struct fstab_rec *recs; - struct fs_mgr_flag_values flag_vals; -#define FS_OPTIONS_LEN 1024 - char tmp_fs_options[FS_OPTIONS_LEN]; - - fstab_file = fopen(fstab_path, "r"); - if (!fstab_file) { - ERROR("Cannot open file %s\n", fstab_path); - return 0; - } - - entries = 0; - while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { - /* if the last character is a newline, shorten the string by 1 byte */ - if (line[len - 1] == '\n') { - line[len - 1] = '\0'; - } - /* Skip any leading whitespace */ - p = line; - while (isspace(*p)) { - p++; - } - /* ignore comments or empty lines */ - if (*p == '#' || *p == '\0') - continue; - entries++; - } - - if (!entries) { - ERROR("No entries found in fstab\n"); - goto err; - } - - /* Allocate and init the fstab structure */ - fstab = calloc(1, sizeof(struct fstab)); - fstab->num_entries = entries; - fstab->fstab_filename = strdup(fstab_path); - fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec)); - - fseek(fstab_file, 0, SEEK_SET); - - cnt = 0; - while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { - /* if the last character is a newline, shorten the string by 1 byte */ - if (line[len - 1] == '\n') { - line[len - 1] = '\0'; - } - - /* Skip any leading whitespace */ - p = line; - while (isspace(*p)) { - p++; - } - /* ignore comments or empty lines */ - if (*p == '#' || *p == '\0') - continue; - - /* If a non-comment entry is greater than the size we allocated, give an - * error and quit. This can happen in the unlikely case the file changes - * between the two reads. - */ - if (cnt >= entries) { - ERROR("Tried to process more entries than counted\n"); - break; - } - - if (!(p = strtok_r(line, delim, &save_ptr))) { - ERROR("Error parsing mount source\n"); - goto err; - } - fstab->recs[cnt].blk_device = strdup(p); - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing mount_point\n"); - goto err; - } - fstab->recs[cnt].mount_point = strdup(p); - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing fs_type\n"); - goto err; - } - fstab->recs[cnt].fs_type = strdup(p); - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing mount_flags\n"); - goto err; - } - tmp_fs_options[0] = '\0'; - fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL, - tmp_fs_options, FS_OPTIONS_LEN); - - /* fs_options are optional */ - if (tmp_fs_options[0]) { - fstab->recs[cnt].fs_options = strdup(tmp_fs_options); - } else { - fstab->recs[cnt].fs_options = NULL; - } - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing fs_mgr_options\n"); - goto err; - } - fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, - &flag_vals, NULL, 0); - fstab->recs[cnt].key_loc = flag_vals.key_loc; - fstab->recs[cnt].length = flag_vals.part_length; - fstab->recs[cnt].label = flag_vals.label; - fstab->recs[cnt].partnum = flag_vals.partnum; - fstab->recs[cnt].swap_prio = flag_vals.swap_prio; - fstab->recs[cnt].zram_size = flag_vals.zram_size; - cnt++; - } - fclose(fstab_file); - free(line); - return fstab; - -err: - fclose(fstab_file); - free(line); - if (fstab) - fs_mgr_free_fstab(fstab); - return NULL; -} - -void fs_mgr_free_fstab(struct fstab *fstab) -{ - int i; - - if (!fstab) { - return; - } - - for (i = 0; i < fstab->num_entries; i++) { - /* Free the pointers return by strdup(3) */ - free(fstab->recs[i].blk_device); - free(fstab->recs[i].mount_point); - free(fstab->recs[i].fs_type); - free(fstab->recs[i].fs_options); - free(fstab->recs[i].key_loc); - free(fstab->recs[i].label); - } - - /* Free the fstab_recs array created by calloc(3) */ - free(fstab->recs); - - /* Free the fstab filename */ - free(fstab->fstab_filename); - - /* Free fstab */ - free(fstab); -} - static void check_fs(char *blk_device, char *fs_type, char *target) { int status; @@ -823,71 +511,3 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev return 0; } - -/* Add an entry to the fstab, and return 0 on success or -1 on error */ -int fs_mgr_add_entry(struct fstab *fstab, - const char *mount_point, const char *fs_type, - const char *blk_device, long long length) -{ - struct fstab_rec *new_fstab_recs; - int n = fstab->num_entries; - - new_fstab_recs = (struct fstab_rec *) - realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1)); - - if (!new_fstab_recs) { - return -1; - } - - /* A new entry was added, so initialize it */ - memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec)); - new_fstab_recs[n].mount_point = strdup(mount_point); - new_fstab_recs[n].fs_type = strdup(fs_type); - new_fstab_recs[n].blk_device = strdup(blk_device); - new_fstab_recs[n].length = 0; - - /* Update the fstab struct */ - fstab->recs = new_fstab_recs; - fstab->num_entries++; - - return 0; -} - -struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) -{ - int i; - - if (!fstab) { - return NULL; - } - - for (i = 0; i < fstab->num_entries; i++) { - int len = strlen(fstab->recs[i].mount_point); - if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && - (path[len] == '\0' || path[len] == '/')) { - return &fstab->recs[i]; - } - } - - return NULL; -} - -int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_VOLDMANAGED; -} - -int fs_mgr_is_nonremovable(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_NONREMOVABLE; -} - -int fs_mgr_is_encryptable(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_CRYPT; -} - -int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_NOEMULATEDSD; -} diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c new file mode 100644 index 0000000..6145771 --- /dev/null +++ b/fs_mgr/fs_mgr_fstab.c @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2014 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 <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mount.h> + +#include "fs_mgr_priv.h" + +struct fs_mgr_flag_values { + char *key_loc; + long long part_length; + char *label; + int partnum; + int swap_prio; + unsigned int zram_size; +}; + +struct flag_list { + const char *name; + unsigned flag; +}; + +static struct flag_list mount_flags[] = { + { "noatime", MS_NOATIME }, + { "noexec", MS_NOEXEC }, + { "nosuid", MS_NOSUID }, + { "nodev", MS_NODEV }, + { "nodiratime", MS_NODIRATIME }, + { "ro", MS_RDONLY }, + { "rw", 0 }, + { "remount", MS_REMOUNT }, + { "bind", MS_BIND }, + { "rec", MS_REC }, + { "unbindable", MS_UNBINDABLE }, + { "private", MS_PRIVATE }, + { "slave", MS_SLAVE }, + { "shared", MS_SHARED }, + { "defaults", 0 }, + { 0, 0 }, +}; + +static struct flag_list fs_mgr_flags[] = { + { "wait", MF_WAIT }, + { "check", MF_CHECK }, + { "encryptable=",MF_CRYPT }, + { "nonremovable",MF_NONREMOVABLE }, + { "voldmanaged=",MF_VOLDMANAGED}, + { "length=", MF_LENGTH }, + { "recoveryonly",MF_RECOVERYONLY }, + { "swapprio=", MF_SWAPPRIO }, + { "zramsize=", MF_ZRAMSIZE }, + { "verify", MF_VERIFY }, + { "noemulatedsd", MF_NOEMULATEDSD }, + { "defaults", 0 }, + { 0, 0 }, +}; + +static int parse_flags(char *flags, struct flag_list *fl, + struct fs_mgr_flag_values *flag_vals, + char *fs_options, int fs_options_len) +{ + int f = 0; + int i; + char *p; + char *savep; + + /* initialize flag values. If we find a relevant flag, we'll + * update the value */ + if (flag_vals) { + memset(flag_vals, 0, sizeof(*flag_vals)); + flag_vals->partnum = -1; + flag_vals->swap_prio = -1; /* negative means it wasn't specified. */ + } + + /* initialize fs_options to the null string */ + if (fs_options && (fs_options_len > 0)) { + fs_options[0] = '\0'; + } + + p = strtok_r(flags, ",", &savep); + while (p) { + /* Look for the flag "p" in the flag list "fl" + * If not found, the loop exits with fl[i].name being null. + */ + for (i = 0; fl[i].name; i++) { + if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { + f |= fl[i].flag; + if ((fl[i].flag == MF_CRYPT) && flag_vals) { + /* The encryptable flag is followed by an = and the + * location of the keys. Get it and return it. + */ + flag_vals->key_loc = strdup(strchr(p, '=') + 1); + } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { + /* The length flag is followed by an = and the + * size of the partition. Get it and return it. + */ + flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0); + } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) { + /* The voldmanaged flag is followed by an = and the + * label, a colon and the partition number or the + * word "auto", e.g. + * voldmanaged=sdcard:3 + * Get and return them. + */ + char *label_start; + char *label_end; + char *part_start; + + label_start = strchr(p, '=') + 1; + label_end = strchr(p, ':'); + if (label_end) { + flag_vals->label = strndup(label_start, + (int) (label_end - label_start)); + part_start = strchr(p, ':') + 1; + if (!strcmp(part_start, "auto")) { + flag_vals->partnum = -1; + } else { + flag_vals->partnum = strtol(part_start, NULL, 0); + } + } else { + ERROR("Warning: voldmanaged= flag malformed\n"); + } + } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) { + flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0); + } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) { + flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0); + } + break; + } + } + + if (!fl[i].name) { + if (fs_options) { + /* It's not a known flag, so it must be a filesystem specific + * option. Add it to fs_options if it was passed in. + */ + strlcat(fs_options, p, fs_options_len); + strlcat(fs_options, ",", fs_options_len); + } else { + /* fs_options was not passed in, so if the flag is unknown + * it's an error. + */ + ERROR("Warning: unknown flag %s\n", p); + } + } + p = strtok_r(NULL, ",", &savep); + } + +out: + if (fs_options && fs_options[0]) { + /* remove the last trailing comma from the list of options */ + fs_options[strlen(fs_options) - 1] = '\0'; + } + + return f; +} + +struct fstab *fs_mgr_read_fstab(const char *fstab_path) +{ + FILE *fstab_file; + int cnt, entries; + ssize_t len; + size_t alloc_len = 0; + char *line = NULL; + const char *delim = " \t"; + char *save_ptr, *p; + struct fstab *fstab = NULL; + struct fstab_rec *recs; + struct fs_mgr_flag_values flag_vals; +#define FS_OPTIONS_LEN 1024 + char tmp_fs_options[FS_OPTIONS_LEN]; + + fstab_file = fopen(fstab_path, "r"); + if (!fstab_file) { + ERROR("Cannot open file %s\n", fstab_path); + return 0; + } + + entries = 0; + while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { + /* if the last character is a newline, shorten the string by 1 byte */ + if (line[len - 1] == '\n') { + line[len - 1] = '\0'; + } + /* Skip any leading whitespace */ + p = line; + while (isspace(*p)) { + p++; + } + /* ignore comments or empty lines */ + if (*p == '#' || *p == '\0') + continue; + entries++; + } + + if (!entries) { + ERROR("No entries found in fstab\n"); + goto err; + } + + /* Allocate and init the fstab structure */ + fstab = calloc(1, sizeof(struct fstab)); + fstab->num_entries = entries; + fstab->fstab_filename = strdup(fstab_path); + fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec)); + + fseek(fstab_file, 0, SEEK_SET); + + cnt = 0; + while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { + /* if the last character is a newline, shorten the string by 1 byte */ + if (line[len - 1] == '\n') { + line[len - 1] = '\0'; + } + + /* Skip any leading whitespace */ + p = line; + while (isspace(*p)) { + p++; + } + /* ignore comments or empty lines */ + if (*p == '#' || *p == '\0') + continue; + + /* If a non-comment entry is greater than the size we allocated, give an + * error and quit. This can happen in the unlikely case the file changes + * between the two reads. + */ + if (cnt >= entries) { + ERROR("Tried to process more entries than counted\n"); + break; + } + + if (!(p = strtok_r(line, delim, &save_ptr))) { + ERROR("Error parsing mount source\n"); + goto err; + } + fstab->recs[cnt].blk_device = strdup(p); + + if (!(p = strtok_r(NULL, delim, &save_ptr))) { + ERROR("Error parsing mount_point\n"); + goto err; + } + fstab->recs[cnt].mount_point = strdup(p); + + if (!(p = strtok_r(NULL, delim, &save_ptr))) { + ERROR("Error parsing fs_type\n"); + goto err; + } + fstab->recs[cnt].fs_type = strdup(p); + + if (!(p = strtok_r(NULL, delim, &save_ptr))) { + ERROR("Error parsing mount_flags\n"); + goto err; + } + tmp_fs_options[0] = '\0'; + fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL, + tmp_fs_options, FS_OPTIONS_LEN); + + /* fs_options are optional */ + if (tmp_fs_options[0]) { + fstab->recs[cnt].fs_options = strdup(tmp_fs_options); + } else { + fstab->recs[cnt].fs_options = NULL; + } + + if (!(p = strtok_r(NULL, delim, &save_ptr))) { + ERROR("Error parsing fs_mgr_options\n"); + goto err; + } + fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, + &flag_vals, NULL, 0); + fstab->recs[cnt].key_loc = flag_vals.key_loc; + fstab->recs[cnt].length = flag_vals.part_length; + fstab->recs[cnt].label = flag_vals.label; + fstab->recs[cnt].partnum = flag_vals.partnum; + fstab->recs[cnt].swap_prio = flag_vals.swap_prio; + fstab->recs[cnt].zram_size = flag_vals.zram_size; + cnt++; + } + fclose(fstab_file); + free(line); + return fstab; + +err: + fclose(fstab_file); + free(line); + if (fstab) + fs_mgr_free_fstab(fstab); + return NULL; +} + +void fs_mgr_free_fstab(struct fstab *fstab) +{ + int i; + + if (!fstab) { + return; + } + + for (i = 0; i < fstab->num_entries; i++) { + /* Free the pointers return by strdup(3) */ + free(fstab->recs[i].blk_device); + free(fstab->recs[i].mount_point); + free(fstab->recs[i].fs_type); + free(fstab->recs[i].fs_options); + free(fstab->recs[i].key_loc); + free(fstab->recs[i].label); + } + + /* Free the fstab_recs array created by calloc(3) */ + free(fstab->recs); + + /* Free the fstab filename */ + free(fstab->fstab_filename); + + /* Free fstab */ + free(fstab); +} + +/* Add an entry to the fstab, and return 0 on success or -1 on error */ +int fs_mgr_add_entry(struct fstab *fstab, + const char *mount_point, const char *fs_type, + const char *blk_device, long long length) +{ + struct fstab_rec *new_fstab_recs; + int n = fstab->num_entries; + + new_fstab_recs = (struct fstab_rec *) + realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1)); + + if (!new_fstab_recs) { + return -1; + } + + /* A new entry was added, so initialize it */ + memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec)); + new_fstab_recs[n].mount_point = strdup(mount_point); + new_fstab_recs[n].fs_type = strdup(fs_type); + new_fstab_recs[n].blk_device = strdup(blk_device); + new_fstab_recs[n].length = 0; + + /* Update the fstab struct */ + fstab->recs = new_fstab_recs; + fstab->num_entries++; + + return 0; +} + +struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) +{ + int i; + + if (!fstab) { + return NULL; + } + + for (i = 0; i < fstab->num_entries; i++) { + int len = strlen(fstab->recs[i].mount_point); + if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && + (path[len] == '\0' || path[len] == '/')) { + return &fstab->recs[i]; + } + } + + return NULL; +} + +int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_VOLDMANAGED; +} + +int fs_mgr_is_nonremovable(struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_NONREMOVABLE; +} + +int fs_mgr_is_encryptable(struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_CRYPT; +} + +int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_NOEMULATEDSD; +} diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c index 1549316..40bc2ec 100644 --- a/fs_mgr/fs_mgr_verity.c +++ b/fs_mgr/fs_mgr_verity.c @@ -36,8 +36,7 @@ #include "mincrypt/sha.h" #include "mincrypt/sha256.h" -#include "ext4_utils.h" -#include "ext4.h" +#include "ext4_sb.h" #include "fs_mgr_priv.h" #include "fs_mgr_priv_verity.h" @@ -122,6 +121,7 @@ static int get_target_device_size(char *blk_device, uint64_t *device_size) { int data_device; struct ext4_super_block sb; + struct fs_info info = {0}; data_device = open(blk_device, O_RDONLY); if (data_device < 0) { @@ -141,7 +141,7 @@ static int get_target_device_size(char *blk_device, uint64_t *device_size) return -1; } - ext4_parse_sb(&sb); + ext4_parse_sb(&sb, &info); *device_size = info.len; close(data_device); 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/include/cutils/debugger.h b/include/cutils/debugger.h index 4eda523..af80e2c 100644 --- a/include/cutils/debugger.h +++ b/include/cutils/debugger.h @@ -23,7 +23,11 @@ extern "C" { #endif +#if __LP64__ +#define DEBUGGER_SOCKET_NAME "android:debuggerd64" +#else #define DEBUGGER_SOCKET_NAME "android:debuggerd" +#endif typedef enum { // dump a crash diff --git a/include/cutils/misc.h b/include/cutils/misc.h index 2c48dfa..0de505f 100644 --- a/include/cutils/misc.h +++ b/include/cutils/misc.h @@ -28,13 +28,6 @@ extern "C" { */ extern void *load_file(const char *fn, unsigned *sz); - /* Connects your process to the system debugger daemon - * so that on a crash it may be logged or interactively - * debugged (depending on system settings). - */ -extern void debuggerd_connect(void); - - /* This is the range of UIDs (and GIDs) that are reserved * for assigning to applications. */ diff --git a/libbacktrace/Android.build.mk b/libbacktrace/Android.build.mk new file mode 100644 index 0000000..3c80cc2 --- /dev/null +++ b/libbacktrace/Android.build.mk @@ -0,0 +1,73 @@ +# +# Copyright (C) 2014 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 $(CLEAR_VARS) + +LOCAL_MODULE := $(module) +LOCAL_MODULE_TAGS := $(module_tag) + +LOCAL_ADDITIONAL_DEPENDENCIES := \ + $(LOCAL_PATH)/Android.mk \ + $(LOCAL_PATH)/Android.build.mk \ + +LOCAL_CFLAGS := \ + $(common_cflags) \ + $($(module)_cflags) \ + $($(module)_cflags_$(build_type)) \ + +LOCAL_CONLYFLAGS += \ + $(common_conlyflags) \ + $($(module)_conlyflags) \ + $($(module)_conlyflags_$(build_type)) \ + +LOCAL_CPPFLAGS += \ + $(common_cppflags) \ + $($(module)_cppflags) \ + $($(module)_cppflags_$(build_type)) \ + +LOCAL_C_INCLUDES := \ + $(common_c_includes) \ + $($(module)_c_includes) \ + $($(module)_c_includes_$(build_type)) \ + +LOCAL_SRC_FILES := \ + $($(module)_src_files) \ + $($(module)_src_files_$(build_type)) \ + +LOCAL_STATIC_LIBRARIES := \ + $($(module)_static_libraries) \ + $($(module)_static_libraries_$(build_type)) \ + +LOCAL_SHARED_LIBRARIES := \ + $($(module)_shared_libraries) \ + $($(module)_shared_libraries_$(build_type)) \ + +LOCAL_LDLIBS := \ + $($(module)_ldlibs) \ + $($(module)_ldlibs_$(build_type)) \ + +ifeq ($(build_type),target) + include external/stlport/libstlport.mk + + include $(BUILD_$(build_target)) +endif + +ifeq ($(build_type),host) + # Only build if host builds are supported. + ifeq ($(build_host),true) + include $(BUILD_HOST_$(build_target)) + endif +endif diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk index 0ae8839..33af0a3 100644..100755 --- a/libbacktrace/Android.mk +++ b/libbacktrace/Android.mk @@ -1,14 +1,23 @@ -LOCAL_PATH:= $(call my-dir) +# +# Copyright (C) 2014 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. +# -common_src := \ - BacktraceImpl.cpp \ - BacktraceMap.cpp \ - BacktraceThread.cpp \ - thread_utils.c \ +LOCAL_PATH:= $(call my-dir) common_cflags := \ -Wall \ - -Wno-unused-parameter \ -Werror \ common_conlyflags := \ @@ -17,274 +26,148 @@ common_conlyflags := \ common_cppflags := \ -std=gnu++11 \ -common_shared_libs := \ +build_host := false +ifeq ($(HOST_OS),linux) +ifeq ($(HOST_ARCH),$(filter $(HOST_ARCH),x86 x86_64)) +build_host := true +endif +endif + +#------------------------------------------------------------------------- +# The libbacktrace library. +#------------------------------------------------------------------------- +libbacktrace_src_files := \ + BacktraceImpl.cpp \ + BacktraceMap.cpp \ + BacktraceThread.cpp \ + thread_utils.c \ + +libbacktrace_shared_libraries_target := \ libcutils \ libgccdemangle \ - liblog \ # To enable using libunwind on each arch, add it to this list. -libunwind_architectures := arm arm64 +libunwind_architectures := arm arm64 x86 x86_64 ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),$(libunwind_architectures))) - -#---------------------------------------------------------------------------- -# The native libbacktrace library with libunwind. -#---------------------------------------------------------------------------- -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - $(common_src) \ +libbacktrace_src_files += \ UnwindCurrent.cpp \ UnwindMap.cpp \ UnwindPtrace.cpp \ -LOCAL_CFLAGS := \ - $(common_cflags) \ - -LOCAL_CONLYFLAGS += \ - $(common_conlyflags) \ - -LOCAL_CPPFLAGS += \ - $(common_cppflags) \ - -LOCAL_MODULE := libbacktrace -LOCAL_MODULE_TAGS := optional - -LOCAL_C_INCLUDES := \ - $(common_c_includes) \ +libbacktrace_c_includes := \ external/libunwind/include \ -LOCAL_SHARED_LIBRARIES := \ - $(common_shared_libs) \ +libbacktrace_shared_libraries := \ libunwind \ libunwind-ptrace \ -LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(LOCAL_PATH)/Android.mk - -include external/stlport/libstlport.mk +libbacktrace_shared_libraries_host := \ + liblog \ -include $(BUILD_SHARED_LIBRARY) +libbacktrace_static_libraries_host := \ + libcutils \ else - -#---------------------------------------------------------------------------- -# The native libbacktrace library with libcorkscrew. -#---------------------------------------------------------------------------- -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - $(common_src) \ +libbacktrace_src_files += \ Corkscrew.cpp \ -LOCAL_CFLAGS := \ - $(common_cflags) \ - -LOCAL_CONLYFLAGS += \ - $(common_conlyflags) \ - -LOCAL_CPPFLAGS += \ - $(common_cppflags) \ - -LOCAL_MODULE := libbacktrace -LOCAL_MODULE_TAGS := optional - -LOCAL_C_INCLUDES := \ - $(common_c_includes) \ +libbacktrace_c_includes := \ system/core/libcorkscrew \ -LOCAL_SHARED_LIBRARIES := \ - $(common_shared_libs) \ +libbacktrace_shared_libraries := \ libcorkscrew \ - libdl \ - -LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(LOCAL_PATH)/Android.mk -include external/stlport/libstlport.mk +libbacktrace_shared_libraries_target += \ + libdl \ -include $(BUILD_SHARED_LIBRARY) +libbacktrace_ldlibs_host := \ + -ldl \ endif -#---------------------------------------------------------------------------- -# libbacktrace test library, all optimizations turned off -#---------------------------------------------------------------------------- -include $(CLEAR_VARS) - -LOCAL_MODULE := libbacktrace_test -LOCAL_MODULE_FLAGS := debug - -LOCAL_SRC_FILES := \ - backtrace_testlib.c - -LOCAL_CFLAGS += \ - -std=gnu99 \ +module := libbacktrace +module_tag := optional +build_type := target +build_target := SHARED_LIBRARY +include $(LOCAL_PATH)/Android.build.mk +build_type := host +include $(LOCAL_PATH)/Android.build.mk + +#------------------------------------------------------------------------- +# The libbacktrace_test library needed by backtrace_test. +#------------------------------------------------------------------------- +libbacktrace_test_cflags := \ -O0 \ -LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(LOCAL_PATH)/Android.mk - -include $(BUILD_SHARED_LIBRARY) - -#---------------------------------------------------------------------------- -# libbacktrace test executable -#---------------------------------------------------------------------------- -include $(CLEAR_VARS) - -LOCAL_MODULE := backtrace_test -LOCAL_MODULE_FLAGS := debug - -LOCAL_SRC_FILES := \ - backtrace_test.cpp \ - thread_utils.c \ - -LOCAL_CFLAGS += \ - $(common_cflags) \ +libbacktrace_test_src_files := \ + backtrace_testlib.c \ + +module := libbacktrace_test +module_tag := debug +build_type := target +build_target := SHARED_LIBRARY +include $(LOCAL_PATH)/Android.build.mk +build_type := host +include $(LOCAL_PATH)/Android.build.mk + +#------------------------------------------------------------------------- +# The backtrace_test executable. +#------------------------------------------------------------------------- +backtrace_test_cflags := \ -fno-builtin \ - -fstack-protector-all \ -O0 \ -g \ - -DGTEST_OS_LINUX_ANDROID \ -DGTEST_HAS_STD_STRING \ -ifeq ($(TARGET_ARCH),arm64) +ifneq ($(TARGET_ARCH),arm64) +backtrace_test_cflags += -fstack-protector-all +else $(info TODO: $(LOCAL_PATH)/Android.mk -fstack-protector not yet available for the AArch64 toolchain) - LOCAL_CFLAGS += -fno-stack-protector + common_cflags += -fno-stack-protector endif # arm64 -LOCAL_CONLYFLAGS += \ - $(common_conlyflags) \ - -LOCAL_CPPFLAGS += \ - $(common_cppflags) \ +backtrace_test_cflags_target := \ + -DGTEST_OS_LINUX_ANDROID \ -LOCAL_SHARED_LIBRARIES += \ - libcutils \ - libbacktrace_test \ - libbacktrace \ +backtrace_test_src_files := \ + backtrace_test.cpp \ + thread_utils.c \ -LOCAL_LDLIBS := \ +backtrace_test_ldlibs := \ -lpthread \ -LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(LOCAL_PATH)/Android.mk - -include $(BUILD_NATIVE_TEST) - -#---------------------------------------------------------------------------- -# Only x86 host versions of libbacktrace supported. -#---------------------------------------------------------------------------- -ifeq ($(HOST_ARCH),x86) - -#---------------------------------------------------------------------------- -# The host libbacktrace library using libcorkscrew -#---------------------------------------------------------------------------- -include $(CLEAR_VARS) - - -LOCAL_CFLAGS += \ - $(common_cflags) \ - -LOCAL_CONLYFLAGS += \ - $(common_conlyflags) \ - -LOCAL_C_INCLUDES := \ - $(common_c_includes) \ - -LOCAL_SHARED_LIBRARIES := \ - libgccdemangle \ - liblog \ - -LOCAL_MODULE := libbacktrace -LOCAL_MODULE_TAGS := optional - -LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(LOCAL_PATH)/Android.mk - -ifeq ($(HOST_OS),linux) -LOCAL_SRC_FILES += \ - $(common_src) \ - Corkscrew.cpp \ - -LOCAL_C_INCLUDES += \ - system/core/libcorkscrew \ - -LOCAL_SHARED_LIBRARIES := \ - libcorkscrew \ - -LOCAL_CPPFLAGS += \ - $(common_cppflags) \ - -LOCAL_LDLIBS += \ - -ldl \ +backtrace_test_ldlibs_host := \ -lrt \ -else -LOCAL_SRC_FILES += \ - BacktraceMap.cpp \ +backtrace_test_shared_libraries := \ + libbacktrace_test \ + libbacktrace \ -endif +backtrace_test_shared_libraries_target := \ + libcutils \ -include $(BUILD_HOST_SHARED_LIBRARY) +module := backtrace_test +module_tag := debug +build_type := target +build_target := NATIVE_TEST +include $(LOCAL_PATH)/Android.build.mk +build_type := host +include $(LOCAL_PATH)/Android.build.mk #---------------------------------------------------------------------------- -# The host test is only supported on linux. +# Special truncated libbacktrace library for mac. #---------------------------------------------------------------------------- -ifeq ($(HOST_OS),linux) +ifeq ($(HOST_OS),darwin) -#---------------------------------------------------------------------------- -# libbacktrace host test library, all optimizations turned off -#---------------------------------------------------------------------------- include $(CLEAR_VARS) -LOCAL_MODULE := libbacktrace_test -LOCAL_MODULE_FLAGS := debug +LOCAL_MODULE := libbacktrace +LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := \ - backtrace_testlib.c - -LOCAL_CFLAGS += \ - -std=gnu99 \ - -O0 \ - -LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(LOCAL_PATH)/Android.mk + BacktraceMap.cpp \ include $(BUILD_HOST_SHARED_LIBRARY) -#---------------------------------------------------------------------------- -# libbacktrace host test executable -#---------------------------------------------------------------------------- -include $(CLEAR_VARS) - -LOCAL_MODULE := backtrace_test -LOCAL_MODULE_FLAGS := debug - -LOCAL_SRC_FILES := \ - backtrace_test.cpp \ - thread_utils.c \ - -LOCAL_CFLAGS += \ - $(common_cflags) \ - -fno-builtin \ - -fstack-protector-all \ - -O0 \ - -g \ - -DGTEST_HAS_STD_STRING \ - -LOCAL_SHARED_LIBRARIES := \ - libbacktrace_test \ - libbacktrace \ - -LOCAL_LDLIBS := \ - -lpthread \ - -LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(LOCAL_PATH)/Android.mk - -include $(BUILD_HOST_NATIVE_TEST) - -endif # HOST_OS == linux - -endif # HOST_ARCH == x86 +endif # HOST_OS-darwin diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp index 39296b4..855810e 100644 --- a/libbacktrace/BacktraceImpl.cpp +++ b/libbacktrace/BacktraceImpl.cpp @@ -21,9 +21,6 @@ #include <sys/types.h> #include <unistd.h> -#define __STDC_FORMAT_MACROS -#include <inttypes.h> - #include <string> #include <backtrace/Backtrace.h> @@ -82,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; @@ -143,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; } } @@ -171,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; } @@ -184,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 17b71b9..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,27 +28,6 @@ #include "UnwindCurrent.h" #include "UnwindMap.h" -// Define the ucontext_t structures needed for each supported arch. -#if defined(__arm__) - // The current version of the <signal.h> doesn't define ucontext_t. - #include <asm/sigcontext.h> // Ensure 'struct sigcontext' is defined. - - // Machine context at the time a signal was raised. - typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - uint32_t uc_sigmask; - } ucontext_t; -#elif defined(__i386__) - #include <asm/sigcontext.h> - #include <asm/ucontext.h> - typedef struct ucontext ucontext_t; -#elif !defined(__mips__) && !defined(__aarch64__) - #error Unsupported architecture. -#endif - //------------------------------------------------------------------------- // UnwindCurrent functions. //------------------------------------------------------------------------- @@ -158,7 +138,7 @@ void UnwindCurrent::ExtractContext(void* sigcontext) { context->regs[13] = uc->uc_mcontext.arm_sp; context->regs[14] = uc->uc_mcontext.arm_lr; context->regs[15] = uc->uc_mcontext.arm_pc; -#elif defined(__mips__) || defined(__i386__) +#else context->uc_mcontext = uc->uc_mcontext; #endif } diff --git a/libbacktrace/UnwindMap.cpp b/libbacktrace/UnwindMap.cpp index 03bb192..8268db6 100644 --- a/libbacktrace/UnwindMap.cpp +++ b/libbacktrace/UnwindMap.cpp @@ -45,7 +45,7 @@ UnwindMap::~UnwindMap() { pthread_mutex_lock(&g_map_mutex); if (--g_map_references == 0) { // Clear the local address space map. - unw_map_set(unw_local_addr_space, NULL); + unw_map_local_set(NULL); unw_map_cursor_destroy(&map_cursor_); } pthread_mutex_unlock(&g_map_mutex); @@ -61,8 +61,8 @@ bool UnwindMap::Build() { if (g_map_references == 0) { return_value = (unw_map_cursor_create(&map_cursor_, pid_) == 0); if (return_value) { - // Set the local address space to this cursor map. - unw_map_set(unw_local_addr_space, &map_cursor_); + // Set the local address space map to our new map. + unw_map_local_set(&map_cursor_); g_map_references = 1; g_map_cursor = map_cursor_; } diff --git a/libcorkscrew/Android.mk b/libcorkscrew/Android.mk index e275317..8f3b68c 100644 --- a/libcorkscrew/Android.mk +++ b/libcorkscrew/Android.mk @@ -30,6 +30,8 @@ x86_src_files := \ arch-x86/backtrace-x86.c \ arch-x86/ptrace-x86.c +ifneq ($(TARGET_IS_64_BIT),true) + include $(CLEAR_VARS) LOCAL_SRC_FILES := $(generic_src_files) @@ -66,9 +68,9 @@ LOCAL_MODULE := libcorkscrew_test LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) +endif # TARGET_IS_64_BIT == false + -# TODO: reenable darwin-x86 -# ifeq ($(HOST_ARCH),x86) ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86) # Build libcorkscrew. @@ -95,4 +97,4 @@ LOCAL_MODULE := libcorkscrew_test LOCAL_MODULE_TAGS := optional include $(BUILD_HOST_EXECUTABLE) -endif # HOST_ARCH == x86 +endif # $(HOST_OS)-$(HOST_ARCH) == linux-x86 diff --git a/libcorkscrew/arch-arm/backtrace-arm.c b/libcorkscrew/arch-arm/backtrace-arm.c index 7bd0d8f..751efbf 100644 --- a/libcorkscrew/arch-arm/backtrace-arm.c +++ b/libcorkscrew/arch-arm/backtrace-arm.c @@ -62,19 +62,7 @@ #include <elf.h> #include <cutils/log.h> -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -/* Old versions of the Android <signal.h> didn't define ucontext_t. */ -#include <asm/sigcontext.h> /* Ensure 'struct sigcontext' is defined. */ - -/* Machine context at the time a signal was raised. */ -typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - uint32_t uc_sigmask; -} ucontext_t; -#endif /* !__BIONIC_HAVE_UCONTEXT_T */ +#include <ucontext.h> /* Unwind state. */ typedef struct { diff --git a/libcorkscrew/arch-mips/backtrace-mips.c b/libcorkscrew/arch-mips/backtrace-mips.c index 57cb324..832fb86 100644 --- a/libcorkscrew/arch-mips/backtrace-mips.c +++ b/libcorkscrew/arch-mips/backtrace-mips.c @@ -36,18 +36,7 @@ #include <sys/ptrace.h> #include <cutils/log.h> -#if defined(__BIONIC__) - -#if defined(__BIONIC_HAVE_UCONTEXT_T) - -// Bionic offers the Linux kernel headers. -#include <asm/sigcontext.h> -#include <asm/ucontext.h> -typedef struct ucontext ucontext_t; - -#else /* __BIONIC_HAVE_UCONTEXT_T */ - -/* Old versions of the Android <signal.h> didn't define ucontext_t. */ +#include <sys/ucontext.h> /* For PTRACE_GETREGS */ typedef struct { @@ -71,30 +60,6 @@ enum { REG_GP, REG_SP, REG_S8, REG_RA, }; -/* Machine context at the time a signal was raised. */ -typedef struct ucontext { - unsigned int sc_regmask; - unsigned int sc_status; - unsigned long long sc_pc; - unsigned long long sc_regs[32]; - unsigned long long sc_fpregs[32]; - unsigned int sc_acx; - unsigned int sc_fpc_csr; - unsigned int sc_fpc_eir; - unsigned int sc_used_math; - unsigned int sc_dsp; - unsigned long long sc_mdhi; - unsigned long long sc_mdlo; - unsigned long sc_hi1; - unsigned long sc_lo1; - unsigned long sc_hi2; - unsigned long sc_lo2; - unsigned long sc_hi3; - unsigned long sc_lo3; -} ucontext_t; - -#endif /* __BIONIC_HAVE_UCONTEXT_T */ -#endif /* Unwind state. */ typedef struct { @@ -896,10 +861,10 @@ ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), const ucontext_t* uc = (const ucontext_t*)sigcontext; unwind_state_t state; - state.reg[DWARF_PC] = uc->sc_pc; - state.reg[DWARF_RA] = uc->sc_regs[REG_RA]; - state.reg[DWARF_FP] = uc->sc_regs[REG_S8]; - state.reg[DWARF_SP] = uc->sc_regs[REG_SP]; + state.reg[DWARF_PC] = uc->uc_mcontext.pc; + state.reg[DWARF_RA] = uc->uc_mcontext.gregs[REG_RA]; + state.reg[DWARF_FP] = uc->uc_mcontext.gregs[REG_S8]; + state.reg[DWARF_SP] = uc->uc_mcontext.gregs[REG_SP]; ALOGV("unwind_backtrace_signal_arch: " "ignore_depth=%d max_depth=%d pc=0x%08x sp=0x%08x ra=0x%08x\n", diff --git a/libcorkscrew/arch-x86/backtrace-x86.c b/libcorkscrew/arch-x86/backtrace-x86.c index ef22821..df486de 100755 --- a/libcorkscrew/arch-x86/backtrace-x86.c +++ b/libcorkscrew/arch-x86/backtrace-x86.c @@ -36,46 +36,7 @@ #include <sys/ptrace.h> #include <cutils/log.h> -#if defined(__BIONIC__) - -#if defined(__BIONIC_HAVE_UCONTEXT_T) - -// Bionic offers the Linux kernel headers. -#include <asm/sigcontext.h> -#include <asm/ucontext.h> -typedef struct ucontext ucontext_t; - -#else /* __BIONIC_HAVE_UCONTEXT_T */ - -/* Old versions of the Android <signal.h> didn't define ucontext_t. */ - -typedef struct { - uint32_t gregs[32]; - void* fpregs; - uint32_t oldmask; - uint32_t cr2; -} mcontext_t; - -enum { - REG_GS = 0, REG_FS, REG_ES, REG_DS, - REG_EDI, REG_ESI, REG_EBP, REG_ESP, - REG_EBX, REG_EDX, REG_ECX, REG_EAX, - REG_TRAPNO, REG_ERR, REG_EIP, REG_CS, - REG_EFL, REG_UESP, REG_SS -}; - -/* Machine context at the time a signal was raised. */ -typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - uint32_t uc_sigmask; -} ucontext_t; - -#endif /* __BIONIC_HAVE_UCONTEXT_T */ - -#elif defined(__APPLE__) +#if defined(__APPLE__) #define _XOPEN_SOURCE #include <ucontext.h> |