155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdio.h> 255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <unistd.h> 355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdlib.h> 455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <inttypes.h> 555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "trace_reader.h" 655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options.h" 755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projecttypedef TraceReader<> TraceReaderType; 955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options-inl.h" 1155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 12921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstrastruct frame { 13921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra uint64_t time; 14921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra uint32_t addr; 15921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra const char *name; 16c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra bool isNative; 17921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 18c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra frame(uint64_t time, uint32_t addr, const char *name, bool isNative) { 19921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra this->time = time; 20921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra this->addr = addr; 21921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra this->name = name; 22c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra this->isNative = isNative; 23921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra } 24921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra}; 25921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 26921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstraclass Stack { 27921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra static const int kMaxFrames = 1000; 28921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra int top; 29921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra frame *frames[kMaxFrames]; 30921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 31921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstrapublic: 32921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra Stack() { 33921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra top = 0; 34921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra } 35921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 36921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra void push(frame *pframe); 37921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra frame* pop(); 38921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra void dump(); 39921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra}; 40921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 41921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstravoid Stack::push(frame *pframe) { 42921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra if (top == kMaxFrames) { 43921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra fprintf(stderr, "Error: stack overflow\n"); 44921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra exit(1); 45921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra } 46921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra frames[top] = pframe; 47921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra top += 1; 48921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra} 49921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 50921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstraframe *Stack::pop() { 51921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra if (top <= 0) 52921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra return NULL; 53921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra top -= 1; 54921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra return frames[top]; 55921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra} 56921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 57921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstravoid Stack::dump() { 58921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra frame *pframe; 59921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 60921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra for (int ii = 0; ii < top; ii++) { 61921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra pframe = frames[ii]; 62c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra const char *native = pframe->isNative ? "n" : " "; 63c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra printf(" %s %d: %llu 0x%x %s\n", 64c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra native, ii, pframe->time, pframe->addr, 65921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra pframe->name == NULL ? "" : pframe->name); 66921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra } 67921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra} 68921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 69921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstrastatic const int kMaxThreads = (32 * 1024); 70921168fdb0cee8ae041df6308b49765b2a98ed74Jack VeenstraStack *stacks[kMaxThreads]; 71921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 7255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectvoid Usage(const char *program) 7355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project{ 7455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project fprintf(stderr, "Usage: %s [options] trace_name elf_file\n", 7555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project program); 7655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project OptionsUsage(); 7755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 7855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 7955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint main(int argc, char **argv) { 8055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ParseOptions(argc, argv); 8155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (argc - optind != 2) { 8255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project Usage(argv[0]); 8355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project exit(1); 8455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 8555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 8655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char *qemu_trace_file = argv[optind++]; 8755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char *elf_file = argv[optind++]; 8855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project TraceReaderType *trace = new TraceReaderType; 8955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->Open(qemu_trace_file); 9055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->ReadKernelSymbols(elf_file); 9155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->SetRoot(root); 9255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 9355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project while (1) { 9455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project MethodRec method_record; 9555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type *sym; 9655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project TraceReaderType::ProcessState *proc; 97921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra frame *pframe; 9855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 9955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (trace->ReadMethodSymbol(&method_record, &sym, &proc)) 10055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project break; 101921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 102921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra if (!IsValidPid(proc->pid)) 103921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra continue; 104921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 10555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (sym != NULL) { 10655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("%lld p %d 0x%x %d %s\n", 10755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project method_record.time, proc->pid, method_record.addr, 10855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project method_record.flags, sym->name); 10955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } else { 11055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("%lld p %d 0x%x %d\n", 11155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project method_record.time, proc->pid, method_record.addr, 11255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project method_record.flags); 11355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 114921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 115921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra // Get the stack for the current thread 116921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra Stack *pStack = stacks[proc->pid]; 117921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 118921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra // If the stack does not exist, then allocate a new one. 119921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra if (pStack == NULL) { 120921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra pStack = new Stack(); 121921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra stacks[proc->pid] = pStack; 122921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra } 123921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra 124c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra int flags = method_record.flags; 125c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra if (flags == kMethodEnter || flags == kNativeEnter) { 126921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra pframe = new frame(method_record.time, method_record.addr, 127c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra sym == NULL ? NULL: sym->name, 128c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra method_record.flags == kNativeEnter); 129921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra pStack->push(pframe); 130921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra } else { 131921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra pframe = pStack->pop(); 132921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra delete pframe; 133921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra } 134921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra pStack->dump(); 13555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 13655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project return 0; 13755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 138