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