Home | History | Annotate | Download | only in qtools
      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