diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index ccc001b97..244edb04d 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -5,7 +5,11 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= debuggerd.c getevent.c unwind-arm.c pr-support.c utility.c symbol_table.c +LOCAL_SRC_FILES:= debuggerd.c utility.c getevent.c $(TARGET_ARCH)/machine.c $(TARGET_ARCH)/unwind.c symbol_table.c +ifeq ($(TARGET_ARCH),arm) +LOCAL_SRC_FILES += $(TARGET_ARCH)/pr-support.c +endif + LOCAL_CFLAGS := -Wall LOCAL_MODULE := debuggerd @@ -22,7 +26,7 @@ include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_SRC_FILES := crasher.c -LOCAL_SRC_FILES += crashglue.S +LOCAL_SRC_FILES += $(TARGET_ARCH)/crashglue.S LOCAL_MODULE := crasher LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) LOCAL_MODULE_TAGS := eng diff --git a/debuggerd/crashglue.S b/debuggerd/arm/crashglue.S similarity index 99% rename from debuggerd/crashglue.S rename to debuggerd/arm/crashglue.S index 0c1fd9b03..eb9d0e38b 100644 --- a/debuggerd/crashglue.S +++ b/debuggerd/arm/crashglue.S @@ -2,7 +2,7 @@ .type crash1, %function .globl crashnostack .type crashnostack, %function - + crash1: ldr r0, =0xa5a50000 ldr r1, =0xa5a50001 diff --git a/debuggerd/arm/machine.c b/debuggerd/arm/machine.c new file mode 100644 index 000000000..ccd0baf18 --- /dev/null +++ b/debuggerd/arm/machine.c @@ -0,0 +1,229 @@ +/* system/debuggerd/debuggerd.c +** +** Copyright 2006, 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "utility.h" + +#ifdef WITH_VFP +#ifdef WITH_VFP_D32 +#define NUM_VFP_REGS 32 +#else +#define NUM_VFP_REGS 16 +#endif +#endif + +/* Main entry point to get the backtrace from the crashing process */ +extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, + unsigned int sp_list[], + int *frame0_pc_sane, + bool at_fault); + +void dump_stack_and_code(int tfd, int pid, mapinfo *map, + int unwind_depth, unsigned int sp_list[], + bool at_fault) +{ + unsigned int sp, pc, p, end, data; + struct pt_regs r; + int sp_depth; + bool only_in_tombstone = !at_fault; + char code_buffer[80]; + + if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; + sp = r.ARM_sp; + pc = r.ARM_pc; + + _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); + + end = p = pc & ~3; + p -= 32; + end += 32; + + /* Dump the code around PC as: + * addr contents + * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c + * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 + */ + while (p <= end) { + int i; + + sprintf(code_buffer, "%08x ", p); + for (i = 0; i < 4; i++) { + data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); + sprintf(code_buffer + strlen(code_buffer), "%08x ", data); + p += 4; + } + _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); + } + + if ((unsigned) r.ARM_lr != pc) { + _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); + + end = p = r.ARM_lr & ~3; + p -= 32; + end += 32; + + /* Dump the code around LR as: + * addr contents + * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c + * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 + */ + while (p <= end) { + int i; + + sprintf(code_buffer, "%08x ", p); + for (i = 0; i < 4; i++) { + data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); + sprintf(code_buffer + strlen(code_buffer), "%08x ", data); + p += 4; + } + _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); + } + } + + p = sp - 64; + p &= ~3; + if (unwind_depth != 0) { + if (unwind_depth < STACK_CONTENT_DEPTH) { + end = sp_list[unwind_depth-1]; + } + else { + end = sp_list[STACK_CONTENT_DEPTH-1]; + } + } + else { + end = sp | 0x000000ff; + end += 0xff; + } + + _LOG(tfd, only_in_tombstone, "\nstack:\n"); + + /* If the crash is due to PC == 0, there will be two frames that + * have identical SP value. + */ + if (sp_list[0] == sp_list[1]) { + sp_depth = 1; + } + else { + sp_depth = 0; + } + + while (p <= end) { + char *prompt; + char level[16]; + data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); + if (p == sp_list[sp_depth]) { + sprintf(level, "#%02d", sp_depth++); + prompt = level; + } + else { + prompt = " "; + } + + /* Print the stack content in the log for the first 3 frames. For the + * rest only print them in the tombstone file. + */ + _LOG(tfd, (sp_depth > 2) || only_in_tombstone, + "%s %08x %08x %s\n", prompt, p, data, + map_to_name(map, data, "")); + p += 4; + } + /* print another 64-byte of stack data after the last frame */ + + end = p+64; + while (p <= end) { + data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); + _LOG(tfd, (sp_depth > 2) || only_in_tombstone, + " %08x %08x %s\n", p, data, + map_to_name(map, data, "")); + p += 4; + } +} + +void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, + bool at_fault) +{ + struct pt_regs r; + + if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { + _LOG(tfd, !at_fault, "tid %d not responding!\n", pid); + return; + } + + if (unwound_level == 0) { + _LOG(tfd, !at_fault, " #%02d pc %08x %s\n", 0, r.ARM_pc, + map_to_name(map, r.ARM_pc, "")); + } + _LOG(tfd, !at_fault, " #%02d lr %08x %s\n", 1, r.ARM_lr, + map_to_name(map, r.ARM_lr, "")); +} + +void dump_registers(int tfd, int pid, bool at_fault) +{ + struct pt_regs r; + bool only_in_tombstone = !at_fault; + + if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { + _LOG(tfd, only_in_tombstone, + "cannot get registers: %s\n", strerror(errno)); + return; + } + + _LOG(tfd, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n", + r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3); + _LOG(tfd, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n", + r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7); + _LOG(tfd, only_in_tombstone, " r8 %08x r9 %08x 10 %08x fp %08x\n", + r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp); + _LOG(tfd, only_in_tombstone, + " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", + r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr); + +#ifdef WITH_VFP + struct user_vfp vfp_regs; + int i; + + if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) { + _LOG(tfd, only_in_tombstone, + "cannot get registers: %s\n", strerror(errno)); + return; + } + + for (i = 0; i < NUM_VFP_REGS; i += 2) { + _LOG(tfd, only_in_tombstone, + " d%-2d %016llx d%-2d %016llx\n", + i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); + } + _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr); +#endif +} diff --git a/debuggerd/pr-support.c b/debuggerd/arm/pr-support.c similarity index 100% rename from debuggerd/pr-support.c rename to debuggerd/arm/pr-support.c diff --git a/debuggerd/unwind-arm.c b/debuggerd/arm/unwind.c similarity index 99% rename from debuggerd/unwind-arm.c rename to debuggerd/arm/unwind.c index b081161a5..d191310fa 100644 --- a/debuggerd/unwind-arm.c +++ b/debuggerd/arm/unwind.c @@ -430,7 +430,7 @@ static _Unwind_Reason_Code log_function(_Unwind_Context *context, pid_t pid, if (pc & 1) { _uw prev_word; pc = (pc & ~1); - prev_word = get_remote_word(pid, (void *) pc-4); + prev_word = get_remote_word(pid, (char *) pc-4); // Long offset if ((prev_word & 0xf0000000) == 0xf0000000 && (prev_word & 0x0000e000) == 0x0000e000) { diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c index f4a5a62bd..00652e975 100644 --- a/debuggerd/crasher.c +++ b/debuggerd/crasher.c @@ -19,6 +19,7 @@ void crash1(void); void crashnostack(void); +void maybeabort(void); static void debuggerd_connect() { diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c index 3b2972acc..eda43cc9d 100644 --- a/debuggerd/debuggerd.c +++ b/debuggerd/debuggerd.c @@ -16,8 +16,6 @@ */ #include -#include -#include #include #include #include @@ -33,31 +31,15 @@ #include #include -#include #include #include #include +#include "debuggerd.h" #include "utility.h" -#ifdef WITH_VFP -#ifdef WITH_VFP_D32 -#define NUM_VFP_REGS 32 -#else -#define NUM_VFP_REGS 16 -#endif -#endif - -/* Main entry point to get the backtrace from the crashing process */ -extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, - unsigned int sp_list[], - int *frame0_pc_sane, - bool at_fault); - -static int logsocket = -1; - #define ANDROID_LOG_INFO 4 /* Log information onto the tombstone */ @@ -79,13 +61,6 @@ void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...) __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap); } -#define LOG(fmt...) _LOG(-1, 0, fmt) -#if 0 -#define XLOG(fmt...) _LOG(-1, 0, fmt) -#else -#define XLOG(fmt...) do {} while(0) -#endif - // 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so // 012345678901234567890123456789012345678901234567890123456789 // 0 1 2 3 4 5 @@ -126,186 +101,6 @@ void dump_build_info(int tfd) _LOG(tfd, false, "Build fingerprint: '%s'\n", fingerprint); } - -void dump_stack_and_code(int tfd, int pid, mapinfo *map, - int unwind_depth, unsigned int sp_list[], - bool at_fault) -{ - unsigned int sp, pc, p, end, data; - struct pt_regs r; - int sp_depth; - bool only_in_tombstone = !at_fault; - char code_buffer[80]; - - if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; - sp = r.ARM_sp; - pc = r.ARM_pc; - - _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); - - end = p = pc & ~3; - p -= 32; - end += 32; - - /* Dump the code around PC as: - * addr contents - * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c - * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 - */ - while (p <= end) { - int i; - - sprintf(code_buffer, "%08x ", p); - for (i = 0; i < 4; i++) { - data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); - sprintf(code_buffer + strlen(code_buffer), "%08x ", data); - p += 4; - } - _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); - } - - if ((unsigned) r.ARM_lr != pc) { - _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); - - end = p = r.ARM_lr & ~3; - p -= 32; - end += 32; - - /* Dump the code around LR as: - * addr contents - * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c - * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 - */ - while (p <= end) { - int i; - - sprintf(code_buffer, "%08x ", p); - for (i = 0; i < 4; i++) { - data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); - sprintf(code_buffer + strlen(code_buffer), "%08x ", data); - p += 4; - } - _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); - } - } - - p = sp - 64; - p &= ~3; - if (unwind_depth != 0) { - if (unwind_depth < STACK_CONTENT_DEPTH) { - end = sp_list[unwind_depth-1]; - } - else { - end = sp_list[STACK_CONTENT_DEPTH-1]; - } - } - else { - end = sp | 0x000000ff; - end += 0xff; - } - - _LOG(tfd, only_in_tombstone, "\nstack:\n"); - - /* If the crash is due to PC == 0, there will be two frames that - * have identical SP value. - */ - if (sp_list[0] == sp_list[1]) { - sp_depth = 1; - } - else { - sp_depth = 0; - } - - while (p <= end) { - char *prompt; - char level[16]; - data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); - if (p == sp_list[sp_depth]) { - sprintf(level, "#%02d", sp_depth++); - prompt = level; - } - else { - prompt = " "; - } - - /* Print the stack content in the log for the first 3 frames. For the - * rest only print them in the tombstone file. - */ - _LOG(tfd, (sp_depth > 2) || only_in_tombstone, - "%s %08x %08x %s\n", prompt, p, data, - map_to_name(map, data, "")); - p += 4; - } - /* print another 64-byte of stack data after the last frame */ - - end = p+64; - while (p <= end) { - data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); - _LOG(tfd, (sp_depth > 2) || only_in_tombstone, - " %08x %08x %s\n", p, data, - map_to_name(map, data, "")); - p += 4; - } -} - -void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, - bool at_fault) -{ - struct pt_regs r; - - if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { - _LOG(tfd, !at_fault, "tid %d not responding!\n", pid); - return; - } - - if (unwound_level == 0) { - _LOG(tfd, !at_fault, " #%02d pc %08x %s\n", 0, r.ARM_pc, - map_to_name(map, r.ARM_pc, "")); - } - _LOG(tfd, !at_fault, " #%02d lr %08x %s\n", 1, r.ARM_lr, - map_to_name(map, r.ARM_lr, "")); -} - -void dump_registers(int tfd, int pid, bool at_fault) -{ - struct pt_regs r; - bool only_in_tombstone = !at_fault; - - if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { - _LOG(tfd, only_in_tombstone, - "cannot get registers: %s\n", strerror(errno)); - return; - } - - _LOG(tfd, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n", - r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3); - _LOG(tfd, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n", - r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7); - _LOG(tfd, only_in_tombstone, " r8 %08x r9 %08x 10 %08x fp %08x\n", - r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp); - _LOG(tfd, only_in_tombstone, - " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", - r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr); - -#ifdef WITH_VFP - struct user_vfp vfp_regs; - int i; - - if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) { - _LOG(tfd, only_in_tombstone, - "cannot get registers: %s\n", strerror(errno)); - return; - } - - for (i = 0; i < NUM_VFP_REGS; i += 2) { - _LOG(tfd, only_in_tombstone, - " d%-2d %016llx d%-2d %016llx\n", - i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); - } - _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr); -#endif -} - const char *get_signame(int sig) { switch(sig) { @@ -377,12 +172,14 @@ static void parse_elf_info(mapinfo *milist, pid_t pid) /* Parse the program header */ get_remote_struct(pid, (char *) ptr+i, &phdr, sizeof(Elf32_Phdr)); +#ifdef __arm__ /* Found a EXIDX segment? */ if (phdr.p_type == PT_ARM_EXIDX) { mi->exidx_start = mi->start + phdr.p_offset; mi->exidx_end = mi->exidx_start + phdr.p_filesz; break; } +#endif } /* Try to load symbols from this file */ @@ -398,7 +195,9 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) mapinfo *milist = 0; unsigned int sp_list[STACK_CONTENT_DEPTH]; int stack_depth; +#ifdef __arm__ int frame0_pc_sane = 1; +#endif if (!at_fault) { _LOG(tfd, true, @@ -426,6 +225,7 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) parse_elf_info(milist, tid); +#if __arm__ /* If stack unwinder fails, use the default solution to dump the stack * content. */ @@ -440,6 +240,7 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) } dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, at_fault); +#endif while(milist) { mapinfo *next = milist->next; @@ -822,10 +623,12 @@ done: if(fd != -1) close(fd); } + int main() { int s; struct sigaction act; + int logsocket = -1; logsocket = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM); diff --git a/debuggerd/debuggerd.h b/debuggerd/debuggerd.h new file mode 100644 index 000000000..01736bdd6 --- /dev/null +++ b/debuggerd/debuggerd.h @@ -0,0 +1,40 @@ +/* system/debuggerd/debuggerd.h +** +** Copyright 2006, 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 +#include +#include +#include "utility.h" +#include "symbol_table.h" + + +/* Main entry point to get the backtrace from the crashing process */ +extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, + unsigned int sp_list[], + int *frame0_pc_sane, + bool at_fault); + +extern void dump_registers(int tfd, int pid, bool at_fault); + +extern int unwind_backtrace_with_ptrace_x86(int tfd, pid_t pid, mapinfo *map, bool at_fault); + +void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, bool at_fault); + +void dump_stack_and_code(int tfd, int pid, mapinfo *map, + int unwind_depth, unsigned int sp_list[], + bool at_fault); + diff --git a/debuggerd/utility.c b/debuggerd/utility.c index 8f3931c1f..a9cbef798 100644 --- a/debuggerd/utility.c +++ b/debuggerd/utility.c @@ -38,14 +38,14 @@ void get_remote_struct(int pid, void *src, void *dst, size_t size) unsigned int i; for (i = 0; i+4 <= size; i+=4) { - *(int *)(dst+i) = ptrace(PTRACE_PEEKTEXT, pid, src+i, NULL); + *(int *)((char *)dst+i) = ptrace(PTRACE_PEEKTEXT, pid, (char *)src+i, NULL); } if (i < size) { int val; assert((size - i) < 4); - val = ptrace(PTRACE_PEEKTEXT, pid, src+i, NULL); + val = ptrace(PTRACE_PEEKTEXT, pid, (char *)src+i, NULL); while (i < size) { ((unsigned char *)dst)[i] = val & 0xff; i++; diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 2ffdf5654..0682b8554 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -56,4 +56,11 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def); /* Log information onto the tombstone */ extern void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...); +#define LOG(fmt...) _LOG(-1, 0, fmt) +#if 0 +#define XLOG(fmt...) _LOG(-1, 0, fmt) +#else +#define XLOG(fmt...) do {} while(0) +#endif + #endif