#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <inttypes.h> #include "trace_reader.h" #include "parse_options.h" typedef TraceReader<> TraceReaderType; #include "parse_options-inl.h" struct frame { uint64_t time; uint32_t addr; const char *name; bool isNative; frame(uint64_t time, uint32_t addr, const char *name, bool isNative) { this->time = time; this->addr = addr; this->name = name; this->isNative = isNative; } }; class Stack { static const int kMaxFrames = 1000; int top; frame *frames[kMaxFrames]; public: Stack() { top = 0; } void push(frame *pframe); frame* pop(); void dump(); }; void Stack::push(frame *pframe) { if (top == kMaxFrames) { fprintf(stderr, "Error: stack overflow\n"); exit(1); } frames[top] = pframe; top += 1; } frame *Stack::pop() { if (top <= 0) return NULL; top -= 1; return frames[top]; } void Stack::dump() { frame *pframe; for (int ii = 0; ii < top; ii++) { pframe = frames[ii]; const char *native = pframe->isNative ? "n" : " "; printf(" %s %d: %llu 0x%x %s\n", native, ii, pframe->time, pframe->addr, pframe->name == NULL ? "" : pframe->name); } } static const int kMaxThreads = (32 * 1024); Stack *stacks[kMaxThreads]; void Usage(const char *program) { fprintf(stderr, "Usage: %s [options] trace_name elf_file\n", program); OptionsUsage(); } int main(int argc, char **argv) { ParseOptions(argc, argv); if (argc - optind != 2) { Usage(argv[0]); exit(1); } char *qemu_trace_file = argv[optind++]; char *elf_file = argv[optind++]; TraceReaderType *trace = new TraceReaderType; trace->Open(qemu_trace_file); trace->ReadKernelSymbols(elf_file); trace->SetRoot(root); while (1) { MethodRec method_record; symbol_type *sym; TraceReaderType::ProcessState *proc; frame *pframe; if (trace->ReadMethodSymbol(&method_record, &sym, &proc)) break; if (!IsValidPid(proc->pid)) continue; if (sym != NULL) { printf("%lld p %d 0x%x %d %s\n", method_record.time, proc->pid, method_record.addr, method_record.flags, sym->name); } else { printf("%lld p %d 0x%x %d\n", method_record.time, proc->pid, method_record.addr, method_record.flags); } // Get the stack for the current thread Stack *pStack = stacks[proc->pid]; // If the stack does not exist, then allocate a new one. if (pStack == NULL) { pStack = new Stack(); stacks[proc->pid] = pStack; } int flags = method_record.flags; if (flags == kMethodEnter || flags == kNativeEnter) { pframe = new frame(method_record.time, method_record.addr, sym == NULL ? NULL: sym->name, method_record.flags == kNativeEnter); pStack->push(pframe); } else { pframe = pStack->pop(); delete pframe; } pStack->dump(); } return 0; }