diff options
Diffstat (limited to 'emulator/qtools/trace_reader_base.h')
-rw-r--r-- | emulator/qtools/trace_reader_base.h | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/emulator/qtools/trace_reader_base.h b/emulator/qtools/trace_reader_base.h new file mode 100644 index 0000000..281d085 --- /dev/null +++ b/emulator/qtools/trace_reader_base.h @@ -0,0 +1,332 @@ +// Copyright 2006 The Android Open Source Project + +#ifndef TRACE_READER_BASE_H +#define TRACE_READER_BASE_H + +#include <inttypes.h> +#include "trace_common.h" +#include "hash_table.h" + +class BBReader; +class InsnReader; +class AddrReader; +class ExcReader; +class PidReader; +class MethodReader; + +struct StaticRec { + uint64_t bb_num; + uint32_t bb_addr; + uint32_t num_insns; +}; + +struct StaticBlock { + StaticRec rec; + uint32_t *insns; +}; + +struct BBEvent { + uint64_t time; + uint64_t bb_num; + uint32_t bb_addr; + uint32_t *insns; + int num_insns; + int pid; + int is_thumb; +}; + +struct PidEvent { + uint64_t time; + int rec_type; // record type: fork, context switch, exit ... + int tgid; // thread group id + int pid; // for fork: child pid; for switch: next pid; + // for exit: exit value + uint32_t vstart; // virtual start address (only used with mmap) + uint32_t vend; // virtual end address (only used with mmap) + uint32_t offset; // virtual file offset (only used with mmap) + + // Dynamically allocated path to executable (or lib). In the case of + // an mmapped dex file, the path is modified to be more useful for + // comparing against the output of dexlist. For example, instead of this: + // /data/dalvik-cache/system@app@TestHarness.apk@classes.dex + // We convert to this: + // /system/app/TestHarness.apk + char *path; + char *mmap_path; // unmodified mmap path + int argc; // number of args + char **argv; // dynamically allocated array of args +}; + +struct MethodRec { + uint64_t time; + uint32_t addr; + int pid; + int flags; +}; + +struct DexSym { + uint32_t addr; + int len; + char *name; +}; + +struct DexFileList { + char *path; + int nsymbols; + DexSym *symbols; +}; + +class TraceReaderBase { + public: + TraceReaderBase(); + virtual ~TraceReaderBase(); + + friend class BBReader; + + void Open(char *filename); + void Close(); + void WriteHeader(TraceHeader *header); + inline bool ReadBB(BBEvent *event); + int ReadStatic(StaticRec *rec); + int ReadStaticInsns(int num, uint32_t *insns); + TraceHeader *GetHeader() { return header_; } + inline uint64_t ReadInsnTime(uint64_t min_time); + void TruncateLastBlock(uint32_t num_insns); + inline bool ReadAddr(uint64_t *time, uint32_t *addr, int *flags); + inline bool ReadExc(uint64_t *time, uint32_t *current_pc, + uint64_t *recnum, uint32_t *target_pc, + uint64_t *bb_num, uint64_t *bb_start_time, + int *num_insns); + inline bool ReadPidEvent(PidEvent *event); + inline bool ReadMethod(MethodRec *method_record); + StaticBlock *GetStaticBlock(uint64_t bb_num) { return &blocks_[bb_num]; } + uint32_t *GetInsns(uint64_t bb_num) { return blocks_[bb_num].insns; } + uint32_t GetBBAddr(uint64_t bb_num) { + return blocks_[bb_num].rec.bb_addr & ~1; + } + int GetIsThumb(uint64_t bb_num) { + return blocks_[bb_num].rec.bb_addr & 1; + } + void SetPostProcessing(bool val) { post_processing_ = val; } + + protected: + virtual int FindCurrentPid(uint64_t time); + int current_pid_; + int next_pid_; + uint64_t next_pid_switch_time_; + PidReader *internal_pid_reader_; + MethodReader *internal_method_reader_; + HashTable<DexFileList*> *dex_hash_; + + private: + int FindNumInsns(uint64_t bb_num, uint64_t bb_start_time); + void ReadTraceHeader(FILE *fstream, char *filename, + char *tracename, TraceHeader *header); + PidEvent *FindMmapDexFileEvent(); + void ParseDexList(char *filename); + + char *static_filename_; + FILE *static_fstream_; + TraceHeader *header_; + BBReader *bb_reader_; + InsnReader *insn_reader_; + AddrReader *load_addr_reader_; + AddrReader *store_addr_reader_; + ExcReader *exc_reader_; + PidReader *pid_reader_; + MethodReader *method_reader_; + ExcReader *internal_exc_reader_; + StaticBlock *blocks_; + bool exc_end_; + uint64_t bb_recnum_; + uint64_t exc_recnum_; + uint64_t exc_bb_num_; + uint64_t exc_time_; + int exc_num_insns_; + bool post_processing_; + + bool load_eof_; + uint64_t load_time_; + uint32_t load_addr_; + bool store_eof_; + uint64_t store_time_; + uint32_t store_addr_; +}; + +class Decoder; + +class BBReader { + public: + explicit BBReader(TraceReaderBase *trace); + ~BBReader(); + void Open(char *filename); + void Close(); + bool ReadBB(BBEvent *event); + + private: + struct TimeRec { + BBRec bb_rec; + uint64_t next_time; + }; + + struct Future { + Future *next; + TimeRec bb; + }; + + inline Future *AllocFuture(); + inline void FreeFuture(Future *future); + inline void InsertFuture(Future *future); + inline int DecodeNextRec(); + + TimeRec nextrec_; + Future futures_[kMaxNumBasicBlocks]; + Future *head_; + Future *free_; + Decoder *decoder_; + bool is_eof_; + TraceReaderBase *trace_; +}; + +class InsnReader { + public: + InsnReader(); + ~InsnReader(); + + void Open(char *filename); + void Close(); + uint64_t ReadInsnTime(uint64_t min_time); + + private: + Decoder *decoder_; + uint64_t prev_time_; + uint64_t time_diff_; + int repeat_; +}; + +class AddrReader { + public: + AddrReader(); + ~AddrReader(); + + bool Open(char *filename, char *suffix); + void Close(); + bool ReadAddr(uint64_t *time, uint32_t *addr); + + private: + Decoder *decoder_; + uint32_t prev_addr_; + uint64_t prev_time_; + bool opened_; // true after file is opened +}; + +class ExcReader { + public: + ExcReader(); + ~ExcReader(); + + void Open(char *filename); + void Close(); + bool ReadExc(uint64_t *time, uint32_t *current_pc, + uint64_t *recnum, uint32_t *target_pc, + uint64_t *bb_num, uint64_t *bb_start_time, + int *num_insns); + + private: + Decoder *decoder_; + uint64_t prev_time_; + uint64_t prev_recnum_; +}; + +class PidReader { + public: + PidReader(); + ~PidReader(); + + void Open(char *filename); + void Close(); + bool ReadPidEvent(struct PidEvent *event); + void Dispose(struct PidEvent *event); + + private: + Decoder *decoder_; + uint64_t prev_time_; +}; + +class MethodReader { + public: + MethodReader(); + ~MethodReader(); + + bool Open(char *filename); + void Close(); + bool ReadMethod(MethodRec *method_record); + + private: + Decoder *decoder_; + uint64_t prev_time_; + uint32_t prev_addr_; + int32_t prev_pid_; + bool opened_; // true after file is opened +}; + +// Reads the next dynamic basic block from the trace. +// Returns true on end-of-file. +inline bool TraceReaderBase::ReadBB(BBEvent *event) +{ + bb_recnum_ += 1; + return bb_reader_->ReadBB(event); +} + +inline uint64_t TraceReaderBase::ReadInsnTime(uint64_t min_time) +{ + return insn_reader_->ReadInsnTime(min_time); +} + +inline bool TraceReaderBase::ReadAddr(uint64_t *time, uint32_t *addr, int *flags) +{ + if (load_eof_ && store_eof_) + return true; + + if (store_eof_ || (!load_eof_ && load_time_ <= store_time_)) { + *time = load_time_; + *addr = load_addr_; + *flags = 0; + load_eof_ = load_addr_reader_->ReadAddr(&load_time_, &load_addr_); + } else { + *time = store_time_; + *addr = store_addr_; + *flags = 1; + store_eof_ = store_addr_reader_->ReadAddr(&store_time_, &store_addr_); + } + return false; +} + +inline bool TraceReaderBase::ReadExc(uint64_t *time, uint32_t *current_pc, + uint64_t *recnum, uint32_t *target_pc, + uint64_t *bb_num, uint64_t *bb_start_time, + int *num_insns) +{ + return exc_reader_->ReadExc(time, current_pc, recnum, target_pc, bb_num, + bb_start_time, num_insns); +} + +inline bool TraceReaderBase::ReadPidEvent(PidEvent *event) +{ + return pid_reader_->ReadPidEvent(event); +} + +inline bool TraceReaderBase::ReadMethod(MethodRec *method_record) +{ + return method_reader_->ReadMethod(method_record); +} + +// Duplicates a string, allocating space using new[]. +inline char * Strdup(const char *src) { + int len = strlen(src); + char *copy = new char[len + 1]; + strcpy(copy, src); + return copy; +} + +#endif /* TRACE_READER_BASE_H */ |