1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <inttypes.h>
5 #include "trace_reader.h"
6 #include "parse_options.h"
7
8 typedef TraceReader<> TraceReaderType;
9
10 #include "parse_options-inl.h"
11
12 struct frame {
13 uint64_t time;
14 uint32_t addr;
15 const char *name;
16 bool isNative;
17
frameframe18 frame(uint64_t time, uint32_t addr, const char *name, bool isNative) {
19 this->time = time;
20 this->addr = addr;
21 this->name = name;
22 this->isNative = isNative;
23 }
24 };
25
26 class Stack {
27 static const int kMaxFrames = 1000;
28 int top;
29 frame *frames[kMaxFrames];
30
31 public:
Stack()32 Stack() {
33 top = 0;
34 }
35
36 void push(frame *pframe);
37 frame* pop();
38 void dump();
39 };
40
push(frame * pframe)41 void Stack::push(frame *pframe) {
42 if (top == kMaxFrames) {
43 fprintf(stderr, "Error: stack overflow\n");
44 exit(1);
45 }
46 frames[top] = pframe;
47 top += 1;
48 }
49
pop()50 frame *Stack::pop() {
51 if (top <= 0)
52 return NULL;
53 top -= 1;
54 return frames[top];
55 }
56
dump()57 void Stack::dump() {
58 frame *pframe;
59
60 for (int ii = 0; ii < top; ii++) {
61 pframe = frames[ii];
62 const char *native = pframe->isNative ? "n" : " ";
63 printf(" %s %d: %llu 0x%x %s\n",
64 native, ii, pframe->time, pframe->addr,
65 pframe->name == NULL ? "" : pframe->name);
66 }
67 }
68
69 static const int kMaxThreads = (32 * 1024);
70 Stack *stacks[kMaxThreads];
71
Usage(const char * program)72 void Usage(const char *program)
73 {
74 fprintf(stderr, "Usage: %s [options] trace_name elf_file\n",
75 program);
76 OptionsUsage();
77 }
78
main(int argc,char ** argv)79 int main(int argc, char **argv) {
80 ParseOptions(argc, argv);
81 if (argc - optind != 2) {
82 Usage(argv[0]);
83 exit(1);
84 }
85
86 char *qemu_trace_file = argv[optind++];
87 char *elf_file = argv[optind++];
88 TraceReaderType *trace = new TraceReaderType;
89 trace->Open(qemu_trace_file);
90 trace->ReadKernelSymbols(elf_file);
91 trace->SetRoot(root);
92
93 while (1) {
94 MethodRec method_record;
95 symbol_type *sym;
96 TraceReaderType::ProcessState *proc;
97 frame *pframe;
98
99 if (trace->ReadMethodSymbol(&method_record, &sym, &proc))
100 break;
101
102 if (!IsValidPid(proc->pid))
103 continue;
104
105 if (sym != NULL) {
106 printf("%lld p %d 0x%x %d %s\n",
107 method_record.time, proc->pid, method_record.addr,
108 method_record.flags, sym->name);
109 } else {
110 printf("%lld p %d 0x%x %d\n",
111 method_record.time, proc->pid, method_record.addr,
112 method_record.flags);
113 }
114
115 // Get the stack for the current thread
116 Stack *pStack = stacks[proc->pid];
117
118 // If the stack does not exist, then allocate a new one.
119 if (pStack == NULL) {
120 pStack = new Stack();
121 stacks[proc->pid] = pStack;
122 }
123
124 int flags = method_record.flags;
125 if (flags == kMethodEnter || flags == kNativeEnter) {
126 pframe = new frame(method_record.time, method_record.addr,
127 sym == NULL ? NULL: sym->name,
128 method_record.flags == kNativeEnter);
129 pStack->push(pframe);
130 } else {
131 pframe = pStack->pop();
132 delete pframe;
133 }
134 pStack->dump();
135 }
136 return 0;
137 }
138