blob: f685cd016bd0b4ab9fd090d05552be80e605fc68 [file] [log] [blame]
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001// 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
Jack Veenstraad6f2532009-05-09 11:44:53 -070018static uint64_t debugTime;
19static uint64_t dumpTime = 0;
20
The Android Open Source Project52d4c302009-03-03 19:29:09 -080021class 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);
Jack Veenstraa476e452009-05-19 16:47:04 -070025 void getFrameType(char *type);
The Android Open Source Project52d4c302009-03-03 19:29:09 -080026};
27
28typedef CallStack<MyFrame> CallStackType;
29
Jack Veenstraa476e452009-05-19 16:47:04 -070030void 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
The Android Open Source Project52d4c302009-03-03 19:29:09 -080043void MyFrame::push(int stackLevel, uint64_t time, CallStackBase *base)
44{
Jack Veenstraa476e452009-05-19 16:47:04 -070045 char type[5];
46
Jack Veenstraad6f2532009-05-09 11:44:53 -070047 if (dumpTime > 0)
48 return;
Jack Veenstraa476e452009-05-19 16:47:04 -070049
50 getFrameType(type);
51 printf("%llu en thr %d %s %3d", time, base->getId(), type, stackLevel);
The Android Open Source Project52d4c302009-03-03 19:29:09 -080052 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{
Jack Veenstraa476e452009-05-19 16:47:04 -070059 char type[5];
60
Jack Veenstraad6f2532009-05-09 11:44:53 -070061 if (dumpTime > 0)
62 return;
Jack Veenstraa476e452009-05-19 16:47:04 -070063
64 getFrameType(type);
65 printf("%llu x thr %d %s %3d", time, base->getId(), type, stackLevel);
The Android Open Source Project52d4c302009-03-03 19:29:09 -080066 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
The Android Open Source Project52d4c302009-03-03 19:29:09 -080075void Usage(const char *program)
76{
Jack Veenstraa476e452009-05-19 16:47:04 -070077 fprintf(stderr, "Usage: %s [options] [-- -d dumpTime] trace_name elf_file\n",
The Android Open Source Project52d4c302009-03-03 19:29:09 -080078 program);
79 OptionsUsage();
80}
81
Jack Veenstraad6f2532009-05-09 11:44:53 -070082bool 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
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800101int main(int argc, char **argv)
102{
103 ParseOptions(argc, argv);
Jack Veenstraad6f2532009-05-09 11:44:53 -0700104 localParseOptions(argc, argv);
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800105 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);
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800116
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);
Jack Veenstraad6f2532009-05-09 11:44:53 -0700140
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 }
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800147 }
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}