• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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);
GetHeader()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);
GetStaticBlock(uint64_t bb_num)102     StaticBlock         *GetStaticBlock(uint64_t bb_num) { return &blocks_[bb_num]; }
GetInsns(uint64_t bb_num)103     uint32_t            *GetInsns(uint64_t bb_num) { return blocks_[bb_num].insns; }
GetBBAddr(uint64_t bb_num)104     uint32_t            GetBBAddr(uint64_t bb_num) {
105         return blocks_[bb_num].rec.bb_addr & ~1;
106     }
GetIsThumb(uint64_t bb_num)107     int                 GetIsThumb(uint64_t bb_num) {
108         return blocks_[bb_num].rec.bb_addr & 1;
109     }
SetPostProcessing(bool val)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.
ReadBB(BBEvent * event)275 inline bool TraceReaderBase::ReadBB(BBEvent *event)
276 {
277     bb_recnum_ += 1;
278     return bb_reader_->ReadBB(event);
279 }
280 
ReadInsnTime(uint64_t min_time)281 inline uint64_t TraceReaderBase::ReadInsnTime(uint64_t min_time)
282 {
283     return insn_reader_->ReadInsnTime(min_time);
284 }
285 
ReadAddr(uint64_t * time,uint32_t * addr,int * flags)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 
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)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 
ReadPidEvent(PidEvent * event)314 inline bool TraceReaderBase::ReadPidEvent(PidEvent *event)
315 {
316     return pid_reader_->ReadPidEvent(event);
317 }
318 
ReadMethod(MethodRec * method_record)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[].
Strdup(const char * src)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