Bruce Beare | 6cc4923 | 2010-10-13 16:11:15 -0700 | [diff] [blame] | 1 | #include <cutils/logd.h> |
| 2 | #include <sys/ptrace.h> |
| 3 | #include "../utility.h" |
| 4 | #include "x86_utility.h" |
| 5 | |
| 6 | |
| 7 | int unwind_backtrace_with_ptrace_x86(int tfd, pid_t pid, mapinfo *map, |
| 8 | bool at_fault) |
| 9 | { |
| 10 | struct pt_regs_x86 r; |
| 11 | unsigned int stack_level = 0; |
| 12 | unsigned int stack_depth = 0; |
| 13 | unsigned int rel_pc; |
| 14 | unsigned int stack_ptr; |
| 15 | unsigned int stack_content; |
| 16 | |
| 17 | if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return 0; |
| 18 | unsigned int eip = (unsigned int)r.eip; |
| 19 | unsigned int ebp = (unsigned int)r.ebp; |
| 20 | unsigned int cur_sp = (unsigned int)r.esp; |
| 21 | const mapinfo *mi; |
| 22 | const struct symbol* sym = 0; |
| 23 | |
| 24 | |
| 25 | //ebp==0, it indicates that the stack is poped to the bottom or there is no stack at all. |
| 26 | while (ebp) { |
Bruce Beare | 6cc4923 | 2010-10-13 16:11:15 -0700 | [diff] [blame] | 27 | mi = pc_to_mapinfo(map, eip, &rel_pc); |
| 28 | |
| 29 | /* See if we can determine what symbol this stack frame resides in */ |
| 30 | if (mi != 0 && mi->symbols != 0) { |
| 31 | sym = symbol_table_lookup(mi->symbols, rel_pc); |
| 32 | } |
| 33 | if (sym) { |
Vladimir Chtchetkine | 714d9de | 2011-06-07 09:24:03 -0700 | [diff] [blame] | 34 | _LOG(tfd, !at_fault, " #%02d eip: %08x %s (%s)\n", |
| 35 | stack_level, eip, mi ? mi->name : "", sym->name); |
Bruce Beare | 6cc4923 | 2010-10-13 16:11:15 -0700 | [diff] [blame] | 36 | } else { |
Vladimir Chtchetkine | 714d9de | 2011-06-07 09:24:03 -0700 | [diff] [blame] | 37 | _LOG(tfd, !at_fault, " #%02d eip: %08x %s\n", |
| 38 | stack_level, eip, mi ? mi->name : ""); |
Bruce Beare | 6cc4923 | 2010-10-13 16:11:15 -0700 | [diff] [blame] | 39 | } |
| 40 | |
| 41 | stack_level++; |
| 42 | if (stack_level >= STACK_DEPTH || eip == 0) |
| 43 | break; |
| 44 | eip = ptrace(PTRACE_PEEKTEXT, pid, (void*)(ebp + 4), NULL); |
| 45 | ebp = ptrace(PTRACE_PEEKTEXT, pid, (void*)ebp, NULL); |
| 46 | } |
| 47 | ebp = (unsigned int)r.ebp; |
| 48 | stack_depth = stack_level; |
| 49 | stack_level = 0; |
| 50 | if (ebp) |
| 51 | _LOG(tfd, !at_fault, "stack: \n"); |
| 52 | while (ebp) { |
Bruce Beare | 6cc4923 | 2010-10-13 16:11:15 -0700 | [diff] [blame] | 53 | stack_ptr = cur_sp; |
| 54 | while((int)(ebp - stack_ptr) >= 0) { |
| 55 | stack_content = ptrace(PTRACE_PEEKTEXT, pid, (void*)stack_ptr, NULL); |
| 56 | mi = pc_to_mapinfo(map, stack_content, &rel_pc); |
| 57 | |
| 58 | /* See if we can determine what symbol this stack frame resides in */ |
| 59 | if (mi != 0 && mi->symbols != 0) { |
| 60 | sym = symbol_table_lookup(mi->symbols, rel_pc); |
| 61 | } |
| 62 | if (sym) { |
Vladimir Chtchetkine | 714d9de | 2011-06-07 09:24:03 -0700 | [diff] [blame] | 63 | _LOG(tfd, !at_fault, " #%02d %08x %08x %s (%s)\n", |
| 64 | stack_level, stack_ptr, stack_content, mi ? mi->name : "", sym->name); |
Bruce Beare | 6cc4923 | 2010-10-13 16:11:15 -0700 | [diff] [blame] | 65 | } else { |
Vladimir Chtchetkine | 714d9de | 2011-06-07 09:24:03 -0700 | [diff] [blame] | 66 | _LOG(tfd, !at_fault, " #%02d %08x %08x %s\n", |
| 67 | stack_level, stack_ptr, stack_content, mi ? mi->name : ""); |
Bruce Beare | 6cc4923 | 2010-10-13 16:11:15 -0700 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | stack_ptr = stack_ptr + 4; |
| 71 | //the stack frame may be very deep. |
| 72 | if((int)(stack_ptr - cur_sp) >= STACK_FRAME_DEPTH) { |
| 73 | _LOG(tfd, !at_fault, " ...... ...... \n"); |
| 74 | break; |
| 75 | } |
| 76 | } |
| 77 | cur_sp = ebp + 4; |
| 78 | stack_level++; |
| 79 | if (stack_level >= STACK_DEPTH || stack_level >= stack_depth) |
| 80 | break; |
| 81 | ebp = ptrace(PTRACE_PEEKTEXT, pid, (void*)ebp, NULL); |
| 82 | } |
| 83 | |
| 84 | return stack_depth; |
| 85 | } |
| 86 | |