aboutsummaryrefslogtreecommitdiffstats
path: root/debuggerd/x86/unwind.c
diff options
context:
space:
mode:
Diffstat (limited to 'debuggerd/x86/unwind.c')
-rw-r--r--debuggerd/x86/unwind.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/debuggerd/x86/unwind.c b/debuggerd/x86/unwind.c
new file mode 100644
index 00000000..8f84e014
--- /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;
+}
+