| #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; |
| } |
| |