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