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