#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) { 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, " #%02d eip: %08x %s (%s)\n", stack_level, eip, mi ? mi->name : "", sym->name); } else { _LOG(tfd, !at_fault, " #%02d eip: %08x %s\n", stack_level, 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) { 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, " #%02d %08x %08x %s (%s)\n", stack_level, stack_ptr, stack_content, mi ? mi->name : "", sym->name); } else { _LOG(tfd, !at_fault, " #%02d %08x %08x %s\n", stack_level, 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; }