Home | History | Annotate | Download | only in qtools
      1 // Copyright 2006 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 static uint64_t debugTime;
     19 static uint64_t dumpTime = 0;
     20 
     21 class MyFrame : public StackFrame<symbol_type> {
     22   public:
     23     void    push(int stackLevel, uint64_t time, CallStackBase *base);
     24     void    pop(int stackLevel, uint64_t time, CallStackBase *base);
     25     void    getFrameType(char *type);
     26 };
     27 
     28 typedef CallStack<MyFrame> CallStackType;
     29 
     30 void MyFrame::getFrameType(char *type)
     31 {
     32     strcpy(type, "----");
     33     if (flags & kCausedException)
     34         type[0] = 'e';
     35     if (flags & kInterpreted)
     36         type[1] = 'm';
     37     if (function->region->flags & region_type::kIsKernelRegion)
     38         type[2] = 'k';
     39     if (function->flags & symbol_type::kIsVectorTable)
     40         type[3] = 'v';
     41 }
     42 
     43 void MyFrame::push(int stackLevel, uint64_t time, CallStackBase *base)
     44 {
     45     char type[5];
     46 
     47     if (dumpTime > 0)
     48         return;
     49 
     50     getFrameType(type);
     51     printf("%llu en thr %d %s %3d", time, base->getId(), type, stackLevel);
     52     for (int ii = 0; ii < stackLevel; ++ii)
     53         printf(".");
     54     printf(" 0x%08x %s\n", addr, function->name);
     55 }
     56 
     57 void MyFrame::pop(int stackLevel, uint64_t time, CallStackBase *base)
     58 {
     59     char type[5];
     60 
     61     if (dumpTime > 0)
     62         return;
     63 
     64     getFrameType(type);
     65     printf("%llu x  thr %d %s %3d", time, base->getId(), type, stackLevel);
     66     for (int ii = 0; ii < stackLevel; ++ii)
     67         printf(".");
     68     printf(" 0x%08x %s\n", addr, function->name);
     69 }
     70 
     71 static const int kNumStackFrames = 500;
     72 static const int kMaxThreads = (32 * 1024);
     73 CallStackType *stacks[kMaxThreads];
     74 
     75 void Usage(const char *program)
     76 {
     77     fprintf(stderr, "Usage: %s [options] [-- -d dumpTime] trace_name elf_file\n",
     78             program);
     79     OptionsUsage();
     80 }
     81 
     82 bool localParseOptions(int argc, char **argv)
     83 {
     84     bool err = false;
     85     while (!err) {
     86         int opt = getopt(argc, argv, "+d:");
     87         if (opt == -1)
     88             break;
     89         switch (opt) {
     90         case 'd':
     91             dumpTime = strtoull(optarg, NULL, 0);
     92             break;
     93         default:
     94             err = true;
     95             break;
     96         }
     97     }
     98     return err;
     99 }
    100 
    101 int main(int argc, char **argv)
    102 {
    103     ParseOptions(argc, argv);
    104     localParseOptions(argc, argv);
    105     if (argc - optind != 2) {
    106         Usage(argv[0]);
    107         exit(1);
    108     }
    109 
    110     char *qemu_trace_file = argv[optind++];
    111     char *elf_file = argv[optind++];
    112     TraceReaderType *trace = new TraceReaderType;
    113     trace->Open(qemu_trace_file);
    114     trace->ReadKernelSymbols(elf_file);
    115     trace->SetRoot(root);
    116 
    117     BBEvent event;
    118     while (1) {
    119         BBEvent ignored;
    120         symbol_type *function;
    121 
    122         if (GetNextValidEvent(trace, &event, &ignored, &function))
    123             break;
    124         if (event.bb_num == 0)
    125             break;
    126 
    127         // Get the stack for the current thread
    128         CallStackType *pStack = stacks[event.pid];
    129 
    130         // If the stack does not exist, then allocate a new one.
    131         if (pStack == NULL) {
    132             pStack = new CallStackType(event.pid, kNumStackFrames, trace);
    133             stacks[event.pid] = pStack;
    134         }
    135         if (debugTime != 0 && event.time >= debugTime)
    136             printf("debug time: %lld\n", debugTime);
    137 
    138         // Update the stack
    139         pStack->updateStack(&event, function);
    140 
    141         // If the user requested a stack dump at a certain time,
    142         // and we are at that time, then dump the stack and exit.
    143         if (dumpTime > 0 && event.time >= dumpTime) {
    144             pStack->showStack(stdout);
    145             break;
    146         }
    147     }
    148 
    149     for (int ii = 0; ii < kMaxThreads; ++ii) {
    150         if (stacks[ii])
    151             stacks[ii]->popAll(event.time);
    152     }
    153 
    154     delete trace;
    155     return 0;
    156 }
    157