aboutsummaryrefslogtreecommitdiffstats
path: root/debuggerd/x86/unwind.c
blob: 8f84e0149ff8e1e8a6c9f6189edbc6a3699c2a3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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;
}