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
13 typedef TraceReader<> TraceReaderType;
14
15 #include "parse_options-inl.h"
16 #include "callstack.h"
17
18 static uint64_t debugTime;
19 static uint64_t dumpTime = 0;
20
21 class 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
28 typedef CallStack<MyFrame> CallStackType;
29
getFrameType(char * type)30 void 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
push(int stackLevel,uint64_t time,CallStackBase * base)43 void 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
pop(int stackLevel,uint64_t time,CallStackBase * base)57 void 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
71 static const int kNumStackFrames = 500;
72 static const int kMaxThreads = (32 * 1024);
73 CallStackType *stacks[kMaxThreads];
74
Usage(const char * program)75 void Usage(const char *program)
76 {
77 fprintf(stderr, "Usage: %s [options] [-- -d dumpTime] trace_name elf_file\n",
78 program);
79 OptionsUsage();
80 }
81
localParseOptions(int argc,char ** argv)82 bool 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
main(int argc,char ** argv)101 int 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