aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/qtools/stack_dump.cpp
blob: f685cd016bd0b4ab9fd090d05552be80e605fc68 (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright 2006 The Android Open Source Project

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "bitvector.h"
#include "parse_options.h"
#include "armdis.h"

typedef TraceReader<> TraceReaderType;

#include "parse_options-inl.h"
#include "callstack.h"

static uint64_t debugTime;
static uint64_t dumpTime = 0;

class MyFrame : public StackFrame<symbol_type> {
  public:
    void    push(int stackLevel, uint64_t time, CallStackBase *base);
    void    pop(int stackLevel, uint64_t time, CallStackBase *base);
    void    getFrameType(char *type);
};

typedef CallStack<MyFrame> CallStackType;

void MyFrame::getFrameType(char *type)
{
    strcpy(type, "----");
    if (flags & kCausedException)
        type[0] = 'e';
    if (flags & kInterpreted)
        type[1] = 'm';
    if (function->region->flags & region_type::kIsKernelRegion)
        type[2] = 'k';
    if (function->flags & symbol_type::kIsVectorTable)
        type[3] = 'v';
}

void MyFrame::push(int stackLevel, uint64_t time, CallStackBase *base)
{
    char type[5];

    if (dumpTime > 0)
        return;

    getFrameType(type);
    printf("%llu en thr %d %s %3d", time, base->getId(), type, stackLevel);
    for (int ii = 0; ii < stackLevel; ++ii)
        printf(".");
    printf(" 0x%08x %s\n", addr, function->name);
}

void MyFrame::pop(int stackLevel, uint64_t time, CallStackBase *base)
{
    char type[5];

    if (dumpTime > 0)
        return;

    getFrameType(type);
    printf("%llu x  thr %d %s %3d", time, base->getId(), type, stackLevel);
    for (int ii = 0; ii < stackLevel; ++ii)
        printf(".");
    printf(" 0x%08x %s\n", addr, function->name);
}

static const int kNumStackFrames = 500;
static const int kMaxThreads = (32 * 1024);
CallStackType *stacks[kMaxThreads];

void Usage(const char *program)
{
    fprintf(stderr, "Usage: %s [options] [-- -d dumpTime] trace_name elf_file\n",
            program);
    OptionsUsage();
}

bool localParseOptions(int argc, char **argv)
{
    bool err = false;
    while (!err) {
        int opt = getopt(argc, argv, "+d:");
        if (opt == -1)
            break;
        switch (opt) {
        case 'd':
            dumpTime = strtoull(optarg, NULL, 0);
            break;
        default:
            err = true;
            break;
        }
    }
    return err;
}

int main(int argc, char **argv)
{
    ParseOptions(argc, argv);
    localParseOptions(argc, argv);
    if (argc - optind != 2) {
        Usage(argv[0]);
        exit(1);
    }

    char *qemu_trace_file = argv[optind++];
    char *elf_file = argv[optind++];
    TraceReaderType *trace = new TraceReaderType;
    trace->Open(qemu_trace_file);
    trace->ReadKernelSymbols(elf_file);
    trace->SetRoot(root);

    BBEvent event;
    while (1) {
        BBEvent ignored;
        symbol_type *function;

        if (GetNextValidEvent(trace, &event, &ignored, &function))
            break;
        if (event.bb_num == 0)
            break;

        // Get the stack for the current thread
        CallStackType *pStack = stacks[event.pid];

        // If the stack does not exist, then allocate a new one.
        if (pStack == NULL) {
            pStack = new CallStackType(event.pid, kNumStackFrames, trace);
            stacks[event.pid] = pStack;
        }
        if (debugTime != 0 && event.time >= debugTime)
            printf("debug time: %lld\n", debugTime);

        // Update the stack
        pStack->updateStack(&event, function);

        // If the user requested a stack dump at a certain time,
        // and we are at that time, then dump the stack and exit.
        if (dumpTime > 0 && event.time >= dumpTime) {
            pStack->showStack(stdout);
            break;
        }
    }

    for (int ii = 0; ii < kMaxThreads; ++ii) {
        if (stacks[ii])
            stacks[ii]->popAll(event.time);
    }

    delete trace;
    return 0;
}