1 // Copyright 2006 The Android Open Source Project 2 3 #ifndef TRACE_READER_BASE_H 4 #define TRACE_READER_BASE_H 5 6 #include <inttypes.h> 7 #include "trace_common.h" 8 #include "hash_table.h" 9 10 class BBReader; 11 class InsnReader; 12 class AddrReader; 13 class ExcReader; 14 class PidReader; 15 class MethodReader; 16 17 struct StaticRec { 18 uint64_t bb_num; 19 uint32_t bb_addr; 20 uint32_t num_insns; 21 }; 22 23 struct StaticBlock { 24 StaticRec rec; 25 uint32_t *insns; 26 }; 27 28 struct BBEvent { 29 uint64_t time; 30 uint64_t bb_num; 31 uint32_t bb_addr; 32 uint32_t *insns; 33 int num_insns; 34 int pid; 35 int is_thumb; 36 }; 37 38 struct PidEvent { 39 uint64_t time; 40 int rec_type; // record type: fork, context switch, exit ... 41 int tgid; // thread group id 42 int pid; // for fork: child pid; for switch: next pid; 43 // for exit: exit value 44 uint32_t vstart; // virtual start address (only used with mmap) 45 uint32_t vend; // virtual end address (only used with mmap) 46 uint32_t offset; // virtual file offset (only used with mmap) 47 48 // Dynamically allocated path to executable (or lib). In the case of 49 // an mmapped dex file, the path is modified to be more useful for 50 // comparing against the output of dexlist. For example, instead of this: 51 // /data/dalvik-cache/system@app (at) TestHarness.apk@classes.dex 52 // We convert to this: 53 // /system/app/TestHarness.apk 54 char *path; 55 char *mmap_path; // unmodified mmap path 56 int argc; // number of args 57 char **argv; // dynamically allocated array of args 58 }; 59 60 struct MethodRec { 61 uint64_t time; 62 uint32_t addr; 63 int pid; 64 int flags; 65 }; 66 67 struct DexSym { 68 uint32_t addr; 69 int len; 70 char *name; 71 }; 72 73 struct DexFileList { 74 char *path; 75 int nsymbols; 76 DexSym *symbols; 77 }; 78 79 class TraceReaderBase { 80 public: 81 TraceReaderBase(); 82 virtual ~TraceReaderBase(); 83 84 friend class BBReader; 85 86 void Open(const char *filename); 87 void Close(); 88 void WriteHeader(TraceHeader *header); 89 inline bool ReadBB(BBEvent *event); 90 int ReadStatic(StaticRec *rec); 91 int ReadStaticInsns(int num, uint32_t *insns); 92 TraceHeader *GetHeader() { return header_; } 93 inline uint64_t ReadInsnTime(uint64_t min_time); 94 void TruncateLastBlock(uint32_t num_insns); 95 inline bool ReadAddr(uint64_t *time, uint32_t *addr, int *flags); 96 inline bool ReadExc(uint64_t *time, uint32_t *current_pc, 97 uint64_t *recnum, uint32_t *target_pc, 98 uint64_t *bb_num, uint64_t *bb_start_time, 99 int *num_insns); 100 inline bool ReadPidEvent(PidEvent *event); 101 inline bool ReadMethod(MethodRec *method_record); 102 StaticBlock *GetStaticBlock(uint64_t bb_num) { return &blocks_[bb_num]; } 103 uint32_t *GetInsns(uint64_t bb_num) { return blocks_[bb_num].insns; } 104 uint32_t GetBBAddr(uint64_t bb_num) { 105 return blocks_[bb_num].rec.bb_addr & ~1; 106 } 107 int GetIsThumb(uint64_t bb_num) { 108 return blocks_[bb_num].rec.bb_addr & 1; 109 } 110 void SetPostProcessing(bool val) { post_processing_ = val; } 111 112 protected: 113 virtual int FindCurrentPid(uint64_t time); 114 int current_pid_; 115 int next_pid_; 116 uint64_t next_pid_switch_time_; 117 PidReader *internal_pid_reader_; 118 MethodReader *internal_method_reader_; 119 HashTable<DexFileList*> *dex_hash_; 120 121 private: 122 int FindNumInsns(uint64_t bb_num, uint64_t bb_start_time); 123 void ReadTraceHeader(FILE *fstream, const char *filename, 124 const char *tracename, TraceHeader *header); 125 PidEvent *FindMmapDexFileEvent(); 126 void ParseDexList(const char *filename); 127 128 char *static_filename_; 129 FILE *static_fstream_; 130 TraceHeader *header_; 131 BBReader *bb_reader_; 132 InsnReader *insn_reader_; 133 AddrReader *load_addr_reader_; 134 AddrReader *store_addr_reader_; 135 ExcReader *exc_reader_; 136 PidReader *pid_reader_; 137 MethodReader *method_reader_; 138 ExcReader *internal_exc_reader_; 139 StaticBlock *blocks_; 140 bool exc_end_; 141 uint64_t bb_recnum_; 142 uint64_t exc_recnum_; 143 uint64_t exc_bb_num_; 144 uint64_t exc_time_; 145 int exc_num_insns_; 146 bool post_processing_; 147 148 bool load_eof_; 149 uint64_t load_time_; 150 uint32_t load_addr_; 151 bool store_eof_; 152 uint64_t store_time_; 153 uint32_t store_addr_; 154 }; 155 156 class Decoder; 157 158 class BBReader { 159 public: 160 explicit BBReader(TraceReaderBase *trace); 161 ~BBReader(); 162 void Open(const char *filename); 163 void Close(); 164 bool ReadBB(BBEvent *event); 165 166 private: 167 struct TimeRec { 168 BBRec bb_rec; 169 uint64_t next_time; 170 }; 171 172 struct Future { 173 Future *next; 174 TimeRec bb; 175 }; 176 177 inline Future *AllocFuture(); 178 inline void FreeFuture(Future *future); 179 inline void InsertFuture(Future *future); 180 inline int DecodeNextRec(); 181 182 TimeRec nextrec_; 183 Future futures_[kMaxNumBasicBlocks]; 184 Future *head_; 185 Future *free_; 186 Decoder *decoder_; 187 bool is_eof_; 188 TraceReaderBase *trace_; 189 }; 190 191 class InsnReader { 192 public: 193 InsnReader(); 194 ~InsnReader(); 195 196 void Open(const char *filename); 197 void Close(); 198 uint64_t ReadInsnTime(uint64_t min_time); 199 200 private: 201 Decoder *decoder_; 202 uint64_t prev_time_; 203 uint64_t time_diff_; 204 int repeat_; 205 }; 206 207 class AddrReader { 208 public: 209 AddrReader(); 210 ~AddrReader(); 211 212 bool Open(const char *filename, const char *suffix); 213 void Close(); 214 bool ReadAddr(uint64_t *time, uint32_t *addr); 215 216 private: 217 Decoder *decoder_; 218 uint32_t prev_addr_; 219 uint64_t prev_time_; 220 bool opened_; // true after file is opened 221 }; 222 223 class ExcReader { 224 public: 225 ExcReader(); 226 ~ExcReader(); 227 228 void Open(const char *filename); 229 void Close(); 230 bool ReadExc(uint64_t *time, uint32_t *current_pc, 231 uint64_t *recnum, uint32_t *target_pc, 232 uint64_t *bb_num, uint64_t *bb_start_time, 233 int *num_insns); 234 235 private: 236 Decoder *decoder_; 237 uint64_t prev_time_; 238 uint64_t prev_recnum_; 239 }; 240 241 class PidReader { 242 public: 243 PidReader(); 244 ~PidReader(); 245 246 void Open(const char *filename); 247 void Close(); 248 bool ReadPidEvent(struct PidEvent *event); 249 void Dispose(struct PidEvent *event); 250 251 private: 252 Decoder *decoder_; 253 uint64_t prev_time_; 254 }; 255 256 class MethodReader { 257 public: 258 MethodReader(); 259 ~MethodReader(); 260 261 bool Open(const char *filename); 262 void Close(); 263 bool ReadMethod(MethodRec *method_record); 264 265 private: 266 Decoder *decoder_; 267 uint64_t prev_time_; 268 uint32_t prev_addr_; 269 int32_t prev_pid_; 270 bool opened_; // true after file is opened 271 }; 272 273 // Reads the next dynamic basic block from the trace. 274 // Returns true on end-of-file. 275 inline bool TraceReaderBase::ReadBB(BBEvent *event) 276 { 277 bb_recnum_ += 1; 278 return bb_reader_->ReadBB(event); 279 } 280 281 inline uint64_t TraceReaderBase::ReadInsnTime(uint64_t min_time) 282 { 283 return insn_reader_->ReadInsnTime(min_time); 284 } 285 286 inline bool TraceReaderBase::ReadAddr(uint64_t *time, uint32_t *addr, int *flags) 287 { 288 if (load_eof_ && store_eof_) 289 return true; 290 291 if (store_eof_ || (!load_eof_ && load_time_ <= store_time_)) { 292 *time = load_time_; 293 *addr = load_addr_; 294 *flags = 0; 295 load_eof_ = load_addr_reader_->ReadAddr(&load_time_, &load_addr_); 296 } else { 297 *time = store_time_; 298 *addr = store_addr_; 299 *flags = 1; 300 store_eof_ = store_addr_reader_->ReadAddr(&store_time_, &store_addr_); 301 } 302 return false; 303 } 304 305 inline bool TraceReaderBase::ReadExc(uint64_t *time, uint32_t *current_pc, 306 uint64_t *recnum, uint32_t *target_pc, 307 uint64_t *bb_num, uint64_t *bb_start_time, 308 int *num_insns) 309 { 310 return exc_reader_->ReadExc(time, current_pc, recnum, target_pc, bb_num, 311 bb_start_time, num_insns); 312 } 313 314 inline bool TraceReaderBase::ReadPidEvent(PidEvent *event) 315 { 316 return pid_reader_->ReadPidEvent(event); 317 } 318 319 inline bool TraceReaderBase::ReadMethod(MethodRec *method_record) 320 { 321 return method_reader_->ReadMethod(method_record); 322 } 323 324 // Duplicates a string, allocating space using new[]. 325 inline char * Strdup(const char *src) { 326 int len = strlen(src); 327 char *copy = new char[len + 1]; 328 strcpy(copy, src); 329 return copy; 330 } 331 332 #endif /* TRACE_READER_BASE_H */ 333