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