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
|
// 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);
};
typedef CallStack<MyFrame> CallStackType;
void MyFrame::push(int stackLevel, uint64_t time, CallStackBase *base)
{
if (dumpTime > 0)
return;
printf("%llu en thr %d %3d", time, base->getId(), 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)
{
if (dumpTime > 0)
return;
printf("%llu x thr %d %3d", time, base->getId(), 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] 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;
}
|