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 13typedef TraceReader<> TraceReaderType; 14 15#include "parse_options-inl.h" 16#include "callstack.h" 17 18static uint64_t debugTime; 19static uint64_t dumpTime = 0; 20 21class 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 28typedef CallStack<MyFrame> CallStackType; 29 30void 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 43void 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 57void 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 71static const int kNumStackFrames = 500; 72static const int kMaxThreads = (32 * 1024); 73CallStackType *stacks[kMaxThreads]; 74 75void Usage(const char *program) 76{ 77 fprintf(stderr, "Usage: %s [options] [-- -d dumpTime] trace_name elf_file\n", 78 program); 79 OptionsUsage(); 80} 81 82bool 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 101int 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