Home | History | Annotate | Download | only in qtools
      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