• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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