]> git.cworth.org Git - apitrace/blob - common/trace_model.hpp
Merge branch 'backtrace'
[apitrace] / common / trace_model.hpp
1 /**************************************************************************
2  *
3  * Copyright 2010 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 /*
27  * Object hierarchy for describing the traces in memory.
28  */
29
30 #ifndef _TRACE_MODEL_HPP_
31 #define _TRACE_MODEL_HPP_
32
33
34 #include <assert.h>
35 #include <stdlib.h>
36
37 #include <map>
38 #include <vector>
39
40
41 namespace trace {
42
43
44 typedef unsigned Id;
45
46
47 struct FunctionSig {
48     Id id;
49     const char *name;
50     unsigned num_args;
51     const char **arg_names;
52 };
53
54
55 struct StructSig {
56     Id id;
57     const char *name;
58     unsigned num_members;
59     const char **member_names;
60 };
61
62
63 struct EnumValue {
64     const char *name;
65     signed long long value;
66 };
67
68
69 struct EnumSig {
70     Id id;
71     unsigned num_values;
72     const EnumValue *values;
73 };
74
75
76 struct BitmaskFlag {
77     const char *name;
78     unsigned long long value;
79 };
80
81
82 struct BitmaskSig {
83     Id id;
84     unsigned num_flags;
85     const BitmaskFlag *flags;
86 };
87
88
89 class Visitor;
90
91
92 class Value
93 {
94 public:
95     virtual ~Value() {}
96     virtual void visit(Visitor &visitor) = 0;
97
98     virtual bool toBool(void) const = 0;
99     virtual signed long long toSInt(void) const;
100     virtual unsigned long long toUInt(void) const;
101     virtual float toFloat(void) const;
102     virtual double toDouble(void) const;
103
104     virtual void *toPointer(void) const;
105     virtual void *toPointer(bool bind);
106     virtual unsigned long long toUIntPtr(void) const;
107     virtual const char *toString(void) const;
108
109     const Value & operator[](size_t index) const;
110 };
111
112
113 class Null : public Value
114 {
115 public:
116     bool toBool(void) const;
117     signed long long toSInt(void) const;
118     unsigned long long toUInt(void) const;
119     virtual float toFloat(void) const;
120     virtual double toDouble(void) const;
121     void *toPointer(void) const;
122     void *toPointer(bool bind);
123     unsigned long long toUIntPtr(void) const;
124     const char *toString(void) const;
125     void visit(Visitor &visitor);
126 };
127
128
129 class Bool : public Value
130 {
131 public:
132     Bool(bool _value) : value(_value) {}
133
134     bool toBool(void) const;
135     signed long long toSInt(void) const;
136     unsigned long long toUInt(void) const;
137     virtual float toFloat(void) const;
138     virtual double toDouble(void) const;
139     void visit(Visitor &visitor);
140
141     bool value;
142 };
143
144
145 class SInt : public Value
146 {
147 public:
148     SInt(signed long long _value) : value(_value) {}
149
150     bool toBool(void) const;
151     signed long long toSInt(void) const;
152     unsigned long long toUInt(void) const;
153     virtual float toFloat(void) const;
154     virtual double toDouble(void) const;
155     void visit(Visitor &visitor);
156
157     signed long long value;
158 };
159
160
161 class UInt : public Value
162 {
163 public:
164     UInt(unsigned long long _value) : value(_value) {}
165
166     bool toBool(void) const;
167     signed long long toSInt(void) const;
168     unsigned long long toUInt(void) const;
169     virtual float toFloat(void) const;
170     virtual double toDouble(void) const;
171     void visit(Visitor &visitor);
172
173     unsigned long long value;
174 };
175
176
177 class Float : public Value
178 {
179 public:
180     Float(float _value) : value(_value) {}
181
182     bool toBool(void) const;
183     signed long long toSInt(void) const;
184     unsigned long long toUInt(void) const;
185     virtual float toFloat(void) const;
186     virtual double toDouble(void) const;
187     void visit(Visitor &visitor);
188
189     float value;
190 };
191
192
193 class Double : public Value
194 {
195 public:
196     Double(double _value) : value(_value) {}
197
198     bool toBool(void) const;
199     signed long long toSInt(void) const;
200     unsigned long long toUInt(void) const;
201     virtual float toFloat(void) const;
202     virtual double toDouble(void) const;
203     void visit(Visitor &visitor);
204
205     double value;
206 };
207
208
209 class String : public Value
210 {
211 public:
212     String(const char * _value) : value(_value) {}
213     ~String();
214
215     bool toBool(void) const;
216     const char *toString(void) const;
217     void visit(Visitor &visitor);
218
219     const char * value;
220 };
221
222
223 class Enum : public SInt
224 {
225 public:
226     Enum(const EnumSig *_sig, signed long long _value) : SInt(_value), sig(_sig) {}
227
228     void visit(Visitor &visitor);
229
230     const EnumSig *sig;
231
232     const EnumValue *
233     lookup() {
234         // TODO: use a std::map
235         for (const EnumValue *it = sig->values; it != sig->values + sig->num_values; ++it) {
236             if (it->value == value) {
237                 return it;
238             }
239         }
240         return NULL;
241     }
242 };
243
244
245 class Bitmask : public UInt
246 {
247 public:
248     Bitmask(const BitmaskSig *_sig, unsigned long long _value) : UInt(_value), sig(_sig) {}
249
250     void visit(Visitor &visitor);
251
252     const BitmaskSig *sig;
253 };
254
255
256 class Struct : public Value
257 {
258 public:
259     Struct(StructSig *_sig) : sig(_sig), members(_sig->num_members) { }
260     ~Struct();
261
262     bool toBool(void) const;
263     void visit(Visitor &visitor);
264
265     const StructSig *sig;
266     std::vector<Value *> members;
267 };
268
269
270 class Array : public Value
271 {
272 public:
273     Array(size_t len) : values(len) {}
274     ~Array();
275
276     bool toBool(void) const;
277     void visit(Visitor &visitor);
278
279     std::vector<Value *> values;
280
281     inline size_t
282     size(void) const {
283         return values.size();
284     }
285 };
286
287
288 class Blob : public Value
289 {
290 public:
291     Blob(size_t _size) {
292         size = _size;
293         buf = new char[_size];
294         bound = false;
295     }
296
297     ~Blob();
298
299     bool toBool(void) const;
300     void *toPointer(void) const;
301     void *toPointer(bool bind);
302     void visit(Visitor &visitor);
303
304     size_t size;
305     char *buf;
306     bool bound;
307 };
308
309
310 class Pointer : public UInt
311 {
312 public:
313     Pointer(unsigned long long value) : UInt(value) {}
314
315     bool toBool(void) const;
316     void *toPointer(void) const;
317     void *toPointer(bool bind);
318     unsigned long long toUIntPtr(void) const;
319     void visit(Visitor &visitor);
320 };
321
322
323 class Repr : public Value
324 {
325 public:
326     Repr(Value *human, Value *machine) :
327         humanValue(human),
328         machineValue(machine)
329     {}
330
331     /** Human-readible value */
332     Value *humanValue;
333
334     /** Machine-readible value */
335     Value *machineValue;
336     
337     virtual bool toBool(void) const;
338     virtual signed long long toSInt(void) const;
339     virtual unsigned long long toUInt(void) const;
340     virtual float toFloat(void) const;
341     virtual double toDouble(void) const;
342
343     virtual void *toPointer(void) const;
344     virtual void *toPointer(bool bind);
345     virtual unsigned long long toUIntPtr(void) const;
346     virtual const char *toString(void) const;
347
348     void visit(Visitor &visitor);
349 };
350
351 struct RawStackFrame {
352     Id id;
353     const char * module;
354     const char * function;
355     const char * filename;
356     int linenumber;
357     long long offset;
358     RawStackFrame() :
359         module(0),
360         function(0),
361         filename(0),
362         linenumber(-1),
363         offset(-1)
364     {
365     }
366 };
367
368 class StackFrame : public RawStackFrame {
369 public:
370     ~StackFrame();
371 };
372
373 typedef std::vector<StackFrame *> Backtrace;
374
375 class Visitor
376 {
377 public:
378     virtual void visit(Null *);
379     virtual void visit(Bool *);
380     virtual void visit(SInt *);
381     virtual void visit(UInt *);
382     virtual void visit(Float *);
383     virtual void visit(Double *);
384     virtual void visit(String *);
385     virtual void visit(Enum *);
386     virtual void visit(Bitmask *);
387     virtual void visit(Struct *);
388     virtual void visit(Array *);
389     virtual void visit(Blob *);
390     virtual void visit(Pointer *);
391     virtual void visit(Repr *);
392     virtual void visit(Backtrace *);
393     virtual void visit(StackFrame *);
394 protected:
395     inline void _visit(Value *value) {
396         if (value) { 
397             value->visit(*this); 
398         }
399     }
400 };
401
402
403 typedef unsigned CallFlags;
404
405 /**
406  * Call flags.
407  *
408  * TODO: It might be better to to record some of these (but not all) into the
409  * trace file.
410  */
411 enum {
412
413     /**
414      * Whether a call was really done by the application or not.
415      *
416      * This flag is set for fake calls -- calls not truly done by the application
417      * but emitted and recorded for completeness, to provide contextual information
418      * necessary for retracing, that would not be available through other ways.
419      *
420      * XXX: This one definetely needs to go into the trace file.
421      */
422     CALL_FLAG_FAKE                      = (1 << 0),
423
424     /**
425      * Whether this call should be retraced or ignored.
426      *
427      * This flag is set for calls which can't be safely replayed (due to incomplete
428      * information) or that have no sideffects.
429      *
430      * Some incomplete calls are unreproduceable, but not all.
431      */
432     CALL_FLAG_NON_REPRODUCIBLE         = (1 << 1),
433     
434     /**
435      * Whether this call has no side-effects, therefore don't need to be
436      * retraced.
437      *
438      * This flag is set for calls that merely query information which is not
439      * needed for posterior calls.
440      */
441     CALL_FLAG_NO_SIDE_EFFECTS            = (1 << 2),
442
443     /**
444      * Whether this call renders into the bound rendertargets.
445      */
446     CALL_FLAG_RENDER                    = (1 << 3),
447
448     /**
449      * Whether this call causes render target to be swapped.
450      *
451      * This does not mark frame termination by itself -- that's solely the
452      * responsibility of `endOfFrame` bit. 
453      *
454      * This mean that snapshots should be take prior to the call, and not
455      * after.
456      */
457     CALL_FLAG_SWAP_RENDERTARGET         = (1 << 4),
458         
459     /**
460      * Whether this call terminates a frame.
461      *
462      * XXX: This can't always be determined by the function name, so it should also
463      * go into the trace file eventually.
464      */
465     CALL_FLAG_END_FRAME                 = (1 << 5),
466
467     /**
468      * Whether this call is incomplete, i.e., it never returned.
469      */
470     CALL_FLAG_INCOMPLETE                = (1 << 6),
471
472     /**
473      * Whether this call is verbose (i.e., not usually interesting).
474      */
475     CALL_FLAG_VERBOSE                  = (1 << 7),
476 };
477
478
479 struct Arg
480 {
481     Value *value;
482 };
483
484
485 class Call
486 {
487 public:
488     unsigned thread_id;
489     unsigned no;
490     const FunctionSig *sig;
491     std::vector<Arg> args;
492     Value *ret;
493
494     CallFlags flags;
495     Backtrace* backtrace;
496
497     Call(const FunctionSig *_sig, const CallFlags &_flags, unsigned _thread_id) :
498         thread_id(_thread_id), 
499         sig(_sig), 
500         args(_sig->num_args), 
501         ret(0),
502         flags(_flags),
503         backtrace(0) {
504     }
505
506     ~Call();
507
508     inline const char * name(void) const {
509         return sig->name;
510     }
511
512     inline Value & arg(unsigned index) {
513         assert(index < args.size());
514         return *(args[index].value);
515     }
516 };
517
518
519 } /* namespace trace */
520
521 #endif /* _TRACE_MODEL_HPP_ */