diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2010-12-13 11:37:40 -0800 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-12-13 11:37:40 -0800 |
commit | 44659e90fe8df25c71195936eabe0cc9158c18a6 (patch) | |
tree | a02c57906a4bdaf708631f369ad4ba2b1c742048 | |
parent | 144773f9e1371a8d4b848c3136b931d5d0687b38 (diff) | |
parent | d3f59eab07d102b9506978aca9541dd62dcea919 (diff) | |
download | system_core-44659e90fe8df25c71195936eabe0cc9158c18a6.zip system_core-44659e90fe8df25c71195936eabe0cc9158c18a6.tar.gz system_core-44659e90fe8df25c71195936eabe0cc9158c18a6.tar.bz2 |
am d3f59eab: Merge "debuggerd: IA version"
* commit 'd3f59eab07d102b9506978aca9541dd62dcea919':
debuggerd: IA version
-rw-r--r-- | debuggerd/Android.mk | 4 | ||||
-rw-r--r-- | debuggerd/arm/unwind.c | 1 | ||||
-rw-r--r-- | debuggerd/debuggerd.c | 7 | ||||
-rw-r--r-- | debuggerd/debuggerd.h | 1 | ||||
-rw-r--r-- | debuggerd/symbol_table.c | 91 | ||||
-rw-r--r-- | debuggerd/symbol_table.h | 1 | ||||
-rw-r--r-- | debuggerd/utility.c | 3 | ||||
-rw-r--r-- | debuggerd/x86/crashglue.S | 15 | ||||
-rw-r--r-- | debuggerd/x86/machine.c | 61 | ||||
-rw-r--r-- | debuggerd/x86/unwind.c | 85 | ||||
-rw-r--r-- | debuggerd/x86/x86_utility.h | 40 |
11 files changed, 285 insertions, 24 deletions
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 244edb0..752c953 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -1,6 +1,6 @@ # Copyright 2005 The Android Open Source Project -ifeq ($(TARGET_ARCH),arm) +ifneq ($(filter arm x86,$(TARGET_ARCH)),) LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -50,4 +50,4 @@ LOCAL_SHARED_LIBRARIES := libcutils libc include $(BUILD_EXECUTABLE) endif # ARCH_ARM_HAVE_VFP == true -endif # TARGET_ARCH == arm +endif # arm or x86 in TARGET_ARCH diff --git a/debuggerd/arm/unwind.c b/debuggerd/arm/unwind.c index d191310..d9600b7 100644 --- a/debuggerd/arm/unwind.c +++ b/debuggerd/arm/unwind.c @@ -451,7 +451,6 @@ static _Unwind_Reason_Code log_function(_Unwind_Context *context, pid_t pid, * 1MB boundaries, and the library may be larger than 1MB. So for .so * addresses we print the relative offset in back trace. */ - rel_pc = pc; mi = pc_to_mapinfo(map, pc, &rel_pc); /* See if we can determine what symbol this stack frame resides in */ diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c index 374a9a5..ecfe01f 100644 --- a/debuggerd/debuggerd.c +++ b/debuggerd/debuggerd.c @@ -286,6 +286,13 @@ 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); +#elif __i386__ + /* If stack unwinder fails, use the default solution to dump the stack + * content. + */ + stack_depth = unwind_backtrace_with_ptrace_x86(tfd, tid, milist,at_fault); +#else +#error "Unsupported architecture" #endif while(milist) { diff --git a/debuggerd/debuggerd.h b/debuggerd/debuggerd.h index 01736bd..e3cdc7c 100644 --- a/debuggerd/debuggerd.h +++ b/debuggerd/debuggerd.h @@ -37,4 +37,3 @@ void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, bool at_f 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/symbol_table.c b/debuggerd/symbol_table.c index 150c058..e76df33 100644 --- a/debuggerd/symbol_table.c +++ b/debuggerd/symbol_table.c @@ -5,6 +5,7 @@ #include <sys/mman.h> #include "symbol_table.h" +#include "utility.h" #include <linux/elf.h> @@ -49,6 +50,7 @@ struct symbol_table *symbol_table_create(const char *filename) int length; char *base; + XLOG("Creating symbol table for %s\n", filename); int fd = open(filename, O_RDONLY); if(fd < 0) { @@ -69,40 +71,70 @@ struct symbol_table *symbol_table_create(const char *filename) Elf32_Shdr *shdr = (Elf32_Shdr*)(base + hdr->e_shoff); // Search for the dynamic symbols section + int sym_idx = -1; int dynsym_idx = -1; int i; for(i = 0; i < hdr->e_shnum; i++) { + if(shdr[i].sh_type == SHT_SYMTAB ) { + sym_idx = i; + } if(shdr[i].sh_type == SHT_DYNSYM ) { dynsym_idx = i; } } - - if(dynsym_idx == -1) { + if ((dynsym_idx == -1) && (sym_idx == -1)) { goto out_unmap; } - Elf32_Sym *dynsyms = (Elf32_Sym*)(base + shdr[dynsym_idx].sh_offset); - int numsyms = shdr[dynsym_idx].sh_size / shdr[dynsym_idx].sh_entsize; - table = malloc(sizeof(struct symbol_table)); if(!table) { goto out_unmap; } + table->name = strdup(filename); table->num_symbols = 0; - // Iterate through the dynamic symbol table, and count how many symbols - // are actually defined - for(i = 0; i < numsyms; i++) { - if(dynsyms[i].st_shndx != SHN_UNDEF) { - table->num_symbols++; - } - } + Elf32_Sym *dynsyms = (Elf32_Sym*)(base + shdr[dynsym_idx].sh_offset); + Elf32_Sym *syms = (Elf32_Sym*)(base + shdr[sym_idx].sh_offset); + + int dynnumsyms = shdr[dynsym_idx].sh_size / shdr[dynsym_idx].sh_entsize; + int numsyms = shdr[sym_idx].sh_size / shdr[sym_idx].sh_entsize; int dynstr_idx = shdr[dynsym_idx].sh_link; + int str_idx = shdr[sym_idx].sh_link; + char *dynstr = base + shdr[dynstr_idx].sh_offset; + char *str = base + shdr[str_idx].sh_offset; + + int symbol_count = 0; + int dynsymbol_count = 0; + + if (dynsym_idx != -1) { + // Iterate through the dynamic symbol table, and count how many symbols + // are actually defined + for(i = 0; i < dynnumsyms; i++) { + if(dynsyms[i].st_shndx != SHN_UNDEF) { + dynsymbol_count++; + } + } + XLOG("Dynamic Symbol count: %d\n", dynsymbol_count); + } + + if (sym_idx != -1) { + // Iterate through the symbol table, and count how many symbols + // are actually defined + for(i = 0; i < numsyms; i++) { + if((syms[i].st_shndx != SHN_UNDEF) && + (strlen(str+syms[i].st_name)) && + (syms[i].st_value != 0) && (syms[i].st_size != 0)) { + symbol_count++; + } + } + XLOG("Symbol count: %d\n", symbol_count); + } // Now, create an entry in our symbol table structure for each symbol... + table->num_symbols += symbol_count + dynsymbol_count;; table->symbols = malloc(table->num_symbols * sizeof(struct symbol)); if(!table->symbols) { free(table); @@ -110,14 +142,35 @@ struct symbol_table *symbol_table_create(const char *filename) goto out_unmap; } - // ...and populate them + int j = 0; - for(i = 0; i < numsyms; i++) { - if(dynsyms[i].st_shndx != SHN_UNDEF) { - table->symbols[j].name = strdup(dynstr + dynsyms[i].st_name); - table->symbols[j].addr = dynsyms[i].st_value; - table->symbols[j].size = dynsyms[i].st_size; - j++; + if (dynsym_idx != -1) { + // ...and populate them + for(i = 0; i < dynnumsyms; i++) { + if(dynsyms[i].st_shndx != SHN_UNDEF) { + table->symbols[j].name = strdup(dynstr + dynsyms[i].st_name); + table->symbols[j].addr = dynsyms[i].st_value; + table->symbols[j].size = dynsyms[i].st_size; + XLOG("name: %s, addr: %x, size: %x\n", + table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size); + j++; + } + } + } + + if (sym_idx != -1) { + // ...and populate them + for(i = 0; i < numsyms; i++) { + if((syms[i].st_shndx != SHN_UNDEF) && + (strlen(str+syms[i].st_name)) && + (syms[i].st_value != 0) && (syms[i].st_size != 0)) { + table->symbols[j].name = strdup(str + syms[i].st_name); + table->symbols[j].addr = syms[i].st_value; + table->symbols[j].size = syms[i].st_size; + XLOG("name: %s, addr: %x, size: %x\n", + table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size); + j++; + } } } diff --git a/debuggerd/symbol_table.h b/debuggerd/symbol_table.h index d9d2520..7f41f91 100644 --- a/debuggerd/symbol_table.h +++ b/debuggerd/symbol_table.h @@ -10,6 +10,7 @@ struct symbol { struct symbol_table { struct symbol *symbols; int num_symbols; + char *name; }; struct symbol_table *symbol_table_create(const char *filename); diff --git a/debuggerd/utility.c b/debuggerd/utility.c index a9cbef7..2afdb46 100644 --- a/debuggerd/utility.c +++ b/debuggerd/utility.c @@ -69,11 +69,12 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def) /* Find the containing map info for the pc */ const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc) { + *rel_pc = pc; while(mi) { if((pc >= mi->start) && (pc < mi->end)){ // Only calculate the relative offset for shared libraries if (strstr(mi->name, ".so")) { - *rel_pc = pc - mi->start; + *rel_pc -= mi->start; } return mi; } diff --git a/debuggerd/x86/crashglue.S b/debuggerd/x86/crashglue.S new file mode 100644 index 0000000..59df432 --- /dev/null +++ b/debuggerd/x86/crashglue.S @@ -0,0 +1,15 @@ +.globl crash1 +.globl crashnostack + +crash1: + movl $0xa5a50000, %eax + movl $0xa5a50001, %ebx + movl $0xa5a50002, %ecx + + movl $0, %edx + jmp *%edx + + +crashnostack: + movl $0, %ebp + jmp *%ebp diff --git a/debuggerd/x86/machine.c b/debuggerd/x86/machine.c new file mode 100644 index 0000000..9d418cf --- /dev/null +++ b/debuggerd/x86/machine.c @@ -0,0 +1,61 @@ +/* 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 <stdio.h> +#include <errno.h> +#include <signal.h> +#include <pthread.h> +#include <fcntl.h> +#include <sys/types.h> +#include <dirent.h> + +#include <sys/ptrace.h> +#include <sys/wait.h> +#include <sys/exec_elf.h> +#include <sys/stat.h> + +#include <cutils/sockets.h> +#include <cutils/properties.h> + +#include <linux/input.h> + +#include "../utility.h" +#include "x86_utility.h" + +void dump_registers(int tfd, int pid, bool at_fault) +{ + struct pt_regs_x86 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; + } +//if there is no stack, no print just like arm + if(!r.ebp) + return; + _LOG(tfd, only_in_tombstone, " eax %08x ebx %08x ecx %08x edx %08x\n", + r.eax, r.ebx, r.ecx, r.edx); + _LOG(tfd, only_in_tombstone, " esi %08x edi %08x\n", + r.esi, r.edi); + _LOG(tfd, only_in_tombstone, " xcs %08x xds %08x xes %08x xfs %08x xss %08x\n", + r.xcs, r.xds, r.xes, r.xfs, r.xss); + _LOG(tfd, only_in_tombstone, + " eip %08x ebp %08x esp %08x flags %08x\n", + r.eip, r.ebp, r.esp, r.eflags); +} diff --git a/debuggerd/x86/unwind.c b/debuggerd/x86/unwind.c new file mode 100644 index 0000000..8f84e01 --- /dev/null +++ b/debuggerd/x86/unwind.c @@ -0,0 +1,85 @@ +#include <cutils/logd.h> +#include <sys/ptrace.h> +#include "../utility.h" +#include "x86_utility.h" + + +int unwind_backtrace_with_ptrace_x86(int tfd, pid_t pid, mapinfo *map, + bool at_fault) +{ + struct pt_regs_x86 r; + unsigned int stack_level = 0; + unsigned int stack_depth = 0; + unsigned int rel_pc; + unsigned int stack_ptr; + unsigned int stack_content; + + if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return 0; + unsigned int eip = (unsigned int)r.eip; + unsigned int ebp = (unsigned int)r.ebp; + unsigned int cur_sp = (unsigned int)r.esp; + const mapinfo *mi; + const struct symbol* sym = 0; + + +//ebp==0, it indicates that the stack is poped to the bottom or there is no stack at all. + while (ebp) { + _LOG(tfd, !at_fault, "#0%d ",stack_level); + mi = pc_to_mapinfo(map, eip, &rel_pc); + + /* See if we can determine what symbol this stack frame resides in */ + if (mi != 0 && mi->symbols != 0) { + sym = symbol_table_lookup(mi->symbols, rel_pc); + } + if (sym) { + _LOG(tfd, !at_fault, " eip: %08x %s (%s)\n", eip, mi ? mi->name : "", sym->name); + } else { + _LOG(tfd, !at_fault, " eip: %08x %s\n", eip, mi ? mi->name : ""); + } + + stack_level++; + if (stack_level >= STACK_DEPTH || eip == 0) + break; + eip = ptrace(PTRACE_PEEKTEXT, pid, (void*)(ebp + 4), NULL); + ebp = ptrace(PTRACE_PEEKTEXT, pid, (void*)ebp, NULL); + } + ebp = (unsigned int)r.ebp; + stack_depth = stack_level; + stack_level = 0; + if (ebp) + _LOG(tfd, !at_fault, "stack: \n"); + while (ebp) { + _LOG(tfd, !at_fault, "#0%d \n",stack_level); + stack_ptr = cur_sp; + while((int)(ebp - stack_ptr) >= 0) { + stack_content = ptrace(PTRACE_PEEKTEXT, pid, (void*)stack_ptr, NULL); + mi = pc_to_mapinfo(map, stack_content, &rel_pc); + + /* See if we can determine what symbol this stack frame resides in */ + if (mi != 0 && mi->symbols != 0) { + sym = symbol_table_lookup(mi->symbols, rel_pc); + } + if (sym) { + _LOG(tfd, !at_fault, " %08x %08x %s (%s)\n", + stack_ptr, stack_content, mi ? mi->name : "", sym->name); + } else { + _LOG(tfd, !at_fault, " %08x %08x %s\n", stack_ptr, stack_content, mi ? mi->name : ""); + } + + stack_ptr = stack_ptr + 4; + //the stack frame may be very deep. + if((int)(stack_ptr - cur_sp) >= STACK_FRAME_DEPTH) { + _LOG(tfd, !at_fault, " ...... ...... \n"); + break; + } + } + cur_sp = ebp + 4; + stack_level++; + if (stack_level >= STACK_DEPTH || stack_level >= stack_depth) + break; + ebp = ptrace(PTRACE_PEEKTEXT, pid, (void*)ebp, NULL); + } + + return stack_depth; +} + diff --git a/debuggerd/x86/x86_utility.h b/debuggerd/x86/x86_utility.h new file mode 100644 index 0000000..ac6a885 --- /dev/null +++ b/debuggerd/x86/x86_utility.h @@ -0,0 +1,40 @@ +/* +** +** 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. +*/ + +#define STACK_DEPTH 8 +#define STACK_FRAME_DEPTH 64 + +typedef struct pt_regs_x86 { + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long eax; + int xds; + int xes; + int xfs; + int xgs; + long orig_eax; + long eip; + int xcs; + long eflags; + long esp; + int xss; +}pt_regs_x86; + |