1 // Copyright 2009 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 typedef CallStack<StackFrame<symbol_type> > CallStackType; 19 20 void compareStacks(uint64_t time, int pid); 21 void dumpStacks(int pid); 22 23 static uint64_t debugTime; 24 static const int kNumStackFrames = 500; 25 static const int kMaxThreads = (32 * 1024); 26 CallStackType *eStacks[kMaxThreads]; 27 28 int numErrors; 29 static const int kMaxErrors = 3; 30 31 struct frame { 32 uint64_t time; 33 uint32_t addr; 34 const char *name; 35 bool isNative; 36 37 frame(uint64_t time, uint32_t addr, const char *name, bool isNative) { 38 this->time = time; 39 this->addr = addr; 40 this->name = name; 41 this->isNative = isNative; 42 } 43 }; 44 45 class Stack { 46 public: 47 static const int kMaxFrames = 1000; 48 int top; 49 frame *frames[kMaxFrames]; 50 51 Stack() { 52 top = 0; 53 } 54 55 void push(frame *pframe); 56 frame* pop(); 57 void dump(); 58 }; 59 60 void Stack::push(frame *pframe) { 61 if (top == kMaxFrames) { 62 fprintf(stderr, "Error: stack overflow\n"); 63 exit(1); 64 } 65 frames[top] = pframe; 66 top += 1; 67 } 68 69 frame *Stack::pop() { 70 if (top <= 0) 71 return NULL; 72 top -= 1; 73 return frames[top]; 74 } 75 76 Stack *mStacks[kMaxThreads]; 77 78 void Usage(const char *program) 79 { 80 fprintf(stderr, "Usage: %s [options] trace_name elf_file\n", 81 program); 82 OptionsUsage(); 83 } 84 85 int main(int argc, char **argv) 86 { 87 ParseOptions(argc, argv); 88 if (argc - optind != 2) { 89 Usage(argv[0]); 90 exit(1); 91 } 92 93 char *qemu_trace_file = argv[optind++]; 94 char *elf_file = argv[optind++]; 95 96 TraceReaderType *etrace = new TraceReaderType; 97 etrace->Open(qemu_trace_file); 98 etrace->ReadKernelSymbols(elf_file); 99 etrace->SetRoot(root); 100 101 TraceReaderType *mtrace = new TraceReaderType; 102 mtrace->Open(qemu_trace_file); 103 mtrace->ReadKernelSymbols(elf_file); 104 mtrace->SetRoot(root); 105 106 BBEvent event; 107 while (1) { 108 BBEvent ignored; 109 symbol_type *function; 110 MethodRec method_record; 111 symbol_type *sym; 112 TraceReaderType::ProcessState *proc; 113 frame *pframe; 114 115 if (mtrace->ReadMethodSymbol(&method_record, &sym, &proc)) 116 break; 117 118 if (!IsValidPid(proc->pid)) 119 continue; 120 121 // Get the stack for the current thread 122 Stack *mStack = mStacks[proc->pid]; 123 124 // If the stack does not exist, then allocate a new one. 125 if (mStack == NULL) { 126 mStack = new Stack(); 127 mStacks[proc->pid] = mStack; 128 } 129 130 int flags = method_record.flags; 131 if (flags == kMethodEnter || flags == kNativeEnter) { 132 pframe = new frame(method_record.time, method_record.addr, 133 sym == NULL ? NULL: sym->name, 134 method_record.flags == kNativeEnter); 135 mStack->push(pframe); 136 } else { 137 pframe = mStack->pop(); 138 delete pframe; 139 } 140 141 do { 142 if (GetNextValidEvent(etrace, &event, &ignored, &function)) 143 break; 144 if (event.bb_num == 0) 145 break; 146 147 // Get the stack for the current thread 148 CallStackType *eStack = eStacks[event.pid]; 149 150 // If the stack does not exist, then allocate a new one. 151 if (eStack == NULL) { 152 eStack = new CallStackType(event.pid, kNumStackFrames, etrace); 153 eStacks[event.pid] = eStack; 154 } 155 if (debugTime != 0 && event.time >= debugTime) 156 printf("time: %llu debug time: %lld\n", event.time, debugTime); 157 158 // Update the stack 159 eStack->updateStack(&event, function); 160 } while (event.time < method_record.time); 161 162 compareStacks(event.time, event.pid); 163 } 164 165 for (int ii = 0; ii < kMaxThreads; ++ii) { 166 if (eStacks[ii]) 167 eStacks[ii]->popAll(event.time); 168 } 169 170 delete etrace; 171 delete mtrace; 172 return 0; 173 } 174 175 void compareStacks(uint64_t time, int pid) { 176 CallStackType *eStack = eStacks[pid]; 177 Stack *mStack = mStacks[pid]; 178 frame **mFrames = mStack->frames; 179 frame *mframe; 180 181 int mTop = mStack->top; 182 int eTop = eStack->mTop; 183 CallStackType::frame_type *eFrames = eStack->mFrames; 184 185 // Count the number of non-native methods (ie, Java methods) on the 186 // Java method stack 187 int numNonNativeMethods = 0; 188 for (int ii = 0; ii < mTop; ++ii) { 189 if (!mFrames[ii]->isNative) { 190 numNonNativeMethods += 1; 191 } 192 } 193 194 // Count the number of Java methods on the native stack 195 int numMethods = 0; 196 for (int ii = 0; ii < eTop; ++ii) { 197 if (eFrames[ii].flags & CallStackType::frame_type::kInterpreted) { 198 numMethods += 1; 199 } 200 } 201 202 // Verify that the number of Java methods on both stacks are the same. 203 // Allow the native stack to have one less Java method because the 204 // native stack might be pushing a native function first. 205 if (numNonNativeMethods != numMethods && numNonNativeMethods != numMethods + 1) { 206 printf("\nDiff at time %llu pid %d: non-native %d numMethods %d\n", 207 time, pid, numNonNativeMethods, numMethods); 208 dumpStacks(pid); 209 numErrors += 1; 210 if (numErrors >= kMaxErrors) 211 exit(1); 212 } 213 214 // Verify that the Java methods on the method stack are the same 215 // as the Java methods on the native stack. 216 int mIndex = 0; 217 for (int ii = 0; ii < eTop; ++ii) { 218 // Ignore native functions on the native stack. 219 if ((eFrames[ii].flags & CallStackType::frame_type::kInterpreted) == 0) 220 continue; 221 uint32_t addr = eFrames[ii].function->addr; 222 addr += eFrames[ii].function->region->vstart; 223 while (mIndex < mTop && mFrames[mIndex]->isNative) { 224 mIndex += 1; 225 } 226 if (mIndex >= mTop) 227 break; 228 if (addr != mFrames[mIndex]->addr) { 229 printf("\nDiff at time %llu pid %d: frame %d\n", time, pid, ii); 230 dumpStacks(pid); 231 exit(1); 232 } 233 mIndex += 1; 234 } 235 } 236 237 void dumpStacks(int pid) { 238 CallStackType *eStack = eStacks[pid]; 239 Stack *mStack = mStacks[pid]; 240 frame *mframe; 241 242 int mTop = mStack->top; 243 printf("\nJava method stack\n"); 244 for (int ii = 0; ii < mTop; ii++) { 245 mframe = mStack->frames[ii]; 246 const char *native = mframe->isNative ? "n" : " "; 247 printf(" %s %d: %llu 0x%x %s\n", 248 native, ii, mframe->time, mframe->addr, 249 mframe->name == NULL ? "" : mframe->name); 250 } 251 252 int eTop = eStack->mTop; 253 CallStackType::frame_type *eFrames = eStack->mFrames; 254 int mIndex = 0; 255 printf("\nNative stack\n"); 256 for (int ii = 0; ii < eTop; ++ii) { 257 uint32_t addr = eFrames[ii].function->addr; 258 addr += eFrames[ii].function->region->vstart; 259 const char *marker = " "; 260 if (eFrames[ii].flags & CallStackType::frame_type::kInterpreted) { 261 if (mIndex >= mTop || addr != mStack->frames[mIndex]->addr) { 262 marker = "*"; 263 } 264 mIndex += 1; 265 } 266 printf(" %s %d: %d f %d 0x%08x %s\n", 267 marker, ii, eFrames[ii].time, eFrames[ii].flags, addr, 268 eFrames[ii].function->name); 269 } 270 } 271