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