1// Copyright 2006 The Android Open Source Project
2
3#include <stdio.h>
4#include <unistd.h>
5#include <stdlib.h>
6#include <inttypes.h>
7#include <assert.h>
8#include "trace_reader.h"
9#include "bitvector.h"
10#include "parse_options.h"
11#include "armdis.h"
12
13typedef TraceReader<> TraceReaderType;
14
15#include "parse_options-inl.h"
16#include "callstack.h"
17
18static uint64_t debugTime;
19static uint64_t dumpTime = 0;
20
21class MyFrame : public StackFrame<symbol_type> {
22  public:
23    void    push(int stackLevel, uint64_t time, CallStackBase *base);
24    void    pop(int stackLevel, uint64_t time, CallStackBase *base);
25    void    getFrameType(char *type);
26};
27
28typedef CallStack<MyFrame> CallStackType;
29
30void MyFrame::getFrameType(char *type)
31{
32    strcpy(type, "----");
33    if (flags & kCausedException)
34        type[0] = 'e';
35    if (flags & kInterpreted)
36        type[1] = 'm';
37    if (function->region->flags & region_type::kIsKernelRegion)
38        type[2] = 'k';
39    if (function->flags & symbol_type::kIsVectorTable)
40        type[3] = 'v';
41}
42
43void MyFrame::push(int stackLevel, uint64_t time, CallStackBase *base)
44{
45    char type[5];
46
47    if (dumpTime > 0)
48        return;
49
50    getFrameType(type);
51    printf("%llu en thr %d %s %3d", time, base->getId(), type, stackLevel);
52    for (int ii = 0; ii < stackLevel; ++ii)
53        printf(".");
54    printf(" 0x%08x %s\n", addr, function->name);
55}
56
57void MyFrame::pop(int stackLevel, uint64_t time, CallStackBase *base)
58{
59    char type[5];
60
61    if (dumpTime > 0)
62        return;
63
64    getFrameType(type);
65    printf("%llu x  thr %d %s %3d", time, base->getId(), type, stackLevel);
66    for (int ii = 0; ii < stackLevel; ++ii)
67        printf(".");
68    printf(" 0x%08x %s\n", addr, function->name);
69}
70
71static const int kNumStackFrames = 500;
72static const int kMaxThreads = (32 * 1024);
73CallStackType *stacks[kMaxThreads];
74
75void Usage(const char *program)
76{
77    fprintf(stderr, "Usage: %s [options] [-- -d dumpTime] trace_name elf_file\n",
78            program);
79    OptionsUsage();
80}
81
82bool localParseOptions(int argc, char **argv)
83{
84    bool err = false;
85    while (!err) {
86        int opt = getopt(argc, argv, "+d:");
87        if (opt == -1)
88            break;
89        switch (opt) {
90        case 'd':
91            dumpTime = strtoull(optarg, NULL, 0);
92            break;
93        default:
94            err = true;
95            break;
96        }
97    }
98    return err;
99}
100
101int main(int argc, char **argv)
102{
103    ParseOptions(argc, argv);
104    localParseOptions(argc, argv);
105    if (argc - optind != 2) {
106        Usage(argv[0]);
107        exit(1);
108    }
109
110    char *qemu_trace_file = argv[optind++];
111    char *elf_file = argv[optind++];
112    TraceReaderType *trace = new TraceReaderType;
113    trace->Open(qemu_trace_file);
114    trace->ReadKernelSymbols(elf_file);
115    trace->SetRoot(root);
116
117    BBEvent event;
118    while (1) {
119        BBEvent ignored;
120        symbol_type *function;
121
122        if (GetNextValidEvent(trace, &event, &ignored, &function))
123            break;
124        if (event.bb_num == 0)
125            break;
126
127        // Get the stack for the current thread
128        CallStackType *pStack = stacks[event.pid];
129
130        // If the stack does not exist, then allocate a new one.
131        if (pStack == NULL) {
132            pStack = new CallStackType(event.pid, kNumStackFrames, trace);
133            stacks[event.pid] = pStack;
134        }
135        if (debugTime != 0 && event.time >= debugTime)
136            printf("debug time: %lld\n", debugTime);
137
138        // Update the stack
139        pStack->updateStack(&event, function);
140
141        // If the user requested a stack dump at a certain time,
142        // and we are at that time, then dump the stack and exit.
143        if (dumpTime > 0 && event.time >= dumpTime) {
144            pStack->showStack(stdout);
145            break;
146        }
147    }
148
149    for (int ii = 0; ii < kMaxThreads; ++ii) {
150        if (stacks[ii])
151            stacks[ii]->popAll(event.time);
152    }
153
154    delete trace;
155    return 0;
156}
157