aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/qtools/trace_reader_base.h
diff options
context:
space:
mode:
Diffstat (limited to 'emulator/qtools/trace_reader_base.h')
-rw-r--r--emulator/qtools/trace_reader_base.h332
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 */