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 18 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: 32 Stack() { 33 top = 0; 34 } 35 36 void push(frame *pframe); 37 frame* pop(); 38 void dump(); 39 }; 40 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 50 frame *Stack::pop() { 51 if (top <= 0) 52 return NULL; 53 top -= 1; 54 return frames[top]; 55 } 56 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 72 void Usage(const char *program) 73 { 74 fprintf(stderr, "Usage: %s [options] trace_name elf_file\n", 75 program); 76 OptionsUsage(); 77 } 78 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