Coverage for /Syzygy/trace/protocol/call_trace_defs.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%110.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #ifndef SYZYGY_TRACE_PROTOCOL_CALL_TRACE_DEFS_H_
  16    :  #define SYZYGY_TRACE_PROTOCOL_CALL_TRACE_DEFS_H_
  17    :  
  18    :  #include <stdint.h>
  19    :  #include <windows.h>
  20    :  #include <wmistr.h>
  21    :  #include <evntrace.h>  // NOLINT - wmistr must precede envtrace.h
  22    :  #include <vector>
  23    :  
  24    :  #include "base/strings/string_piece.h"
  25    :  #include "syzygy/common/assertions.h"
  26    :  #include "syzygy/trace/common/clock.h"
  27    :  
  28    :  // ID for the call trace provider.
  29    :  extern const GUID kCallTraceProvider;
  30    :  
  31    :  // Class of trace provider events.
  32    :  extern const GUID kCallTraceEventClass;
  33    :  
  34    :  // GUID for the kernel trace control interface.
  35    :  extern const GUID kSystemTraceControlGuid;
  36    :  
  37    :  // This is the absolute minimum number of buffers we will allow, across all
  38    :  // CPUs.
  39    :  extern const size_t kMinEtwBuffers;
  40    :  
  41    :  // This is the minimum number of buffers per CPU we'll allow.
  42    :  extern const size_t kMinEtwBuffersPerProcessor;
  43    :  
  44    :  // Max buffers will be min buffers * kEtwBufferMultiplier.
  45    :  extern const size_t kEtwBufferMultiplier;
  46    :  
  47    :  // The set of flags to use when logging trace events via ETW.
  48    :  extern const int kDefaultEtwTraceFlags;
  49    :  
  50    :  // The set of flags to use when logging kernel events via ETW.
  51    :  extern const int kDefaultEtwKernelFlags;
  52    :  
  53    :  // RPC protocol and endpoint.
  54    :  extern const char kSyzygyRpcInstanceIdEnvVar[];
  55    :  void GetSyzygyCallTraceRpcProtocol(std::wstring* protocol);
  56    :  void GetSyzygyCallTraceRpcEndpoint(const base::StringPiece16& id,
  57    :                                     std::wstring* endpoint);
  58    :  void GetSyzygyCallTraceRpcMutexName(const base::StringPiece16& id,
  59    :                                      std::wstring* mutex_name);
  60    :  void GetSyzygyCallTraceRpcEventName(const base::StringPiece16& id,
  61    :                                      std::wstring* event_name);
  62    :  
  63    :  // Environment variable used to indicate that an RPC session is mandatory.
  64    :  extern const char kSyzygyRpcSessionMandatoryEnvVar[];
  65    :  
  66    :  // This must be bumped anytime the file format is changed.
  67    :  enum {
  68    :    TRACE_VERSION_HI = 1,
  69    :    TRACE_VERSION_LO = 4,
  70    :  };
  71    :  
  72    :  enum TraceEventType {
  73    :    // Header prefix for a "page" of call trace events.
  74    :    TRACE_PAGE_HEADER,
  75    :    // The actual events are below.
  76    :    TRACE_PROCESS_STARTED = 10,
  77    :    TRACE_PROCESS_ENDED,
  78    :    TRACE_ENTER_EVENT,
  79    :    TRACE_EXIT_EVENT,
  80    :    TRACE_PROCESS_ATTACH_EVENT,
  81    :    TRACE_PROCESS_DETACH_EVENT,
  82    :    TRACE_THREAD_ATTACH_EVENT,
  83    :    TRACE_THREAD_DETACH_EVENT,
  84    :    TRACE_MODULE_EVENT,
  85    :    TRACE_BATCH_ENTER,
  86    :    TRACE_BATCH_INVOCATION,
  87    :    TRACE_THREAD_NAME,
  88    :    TRACE_INDEXED_FREQUENCY,
  89    :    TRACE_DYNAMIC_SYMBOL,
  90    :    TRACE_SAMPLE_DATA,
  91    :    TRACE_FUNCTION_NAME_TABLE_ENTRY,
  92    :    TRACE_STACK_TRACE,
  93    :    TRACE_DETAILED_FUNCTION_CALL,
  94    :    TRACE_COMMENT,
  95    :    TRACE_PROCESS_HEAP,
  96    :  };
  97    :  
  98    :  // All traces are emitted at this trace level.
  99    :  const UCHAR CALL_TRACE_LEVEL = TRACE_LEVEL_INFORMATION;
 100    :  
 101    :  enum TraceEventFlags {
 102    :    // Trace function entry.
 103    :    TRACE_FLAG_ENTER          = 0x0001,
 104    :    // Trace function exit.
 105    :    TRACE_FLAG_EXIT           = 0x0002,
 106    :    // Capture stack traces on entry and exit.
 107    :    TRACE_FLAG_STACK_TRACES   = 0x0004,
 108    :    // Trace DLL load/unload events.
 109    :    TRACE_FLAG_LOAD_EVENTS    = 0x0008,
 110    :    // Trace DLL thread events.
 111    :    TRACE_FLAG_THREAD_EVENTS  = 0x0010,
 112    :    // Batch entry traces.
 113    :    TRACE_FLAG_BATCH_ENTER    = 0x0020,
 114    :  };
 115    :  
 116    :  // Max depth of stack trace captured on entry/exit.
 117    :  const size_t kMaxTraceDepth = 32;
 118    :  
 119    :  typedef const void* RetAddr;
 120    :  typedef const void* FuncAddr;
 121    :  typedef const void* ModuleAddr;
 122    :  typedef DWORD ArgumentWord;
 123    :  typedef DWORD RetValueWord;
 124    :  typedef void* SessionHandle;
 125    :  
 126    :  // A prefix for each trace record on disk.
 127    :  struct RecordPrefix {
 128    :    // The timestamp of the trace event.
 129    :    uint64_t timestamp;
 130    :  
 131    :    // The size of the record, in bytes;
 132    :    uint32_t size;
 133    :  
 134    :    // The type of trace record.  Will be a value from the TraceEventType
 135    :    // enumeration.
 136    :    uint16_t type;
 137    :  
 138    :    // If the call trace service aggregates all trace records to a single
 139    :    // file, instead of a file per process, then it's possible that a
 140    :    // single file could contain traces produced by multiple versions of
 141    :    // the client library.
 142    :    struct {
 143    :      uint8_t hi;
 144    :      uint8_t lo;
 145    :    } version;
 146    :  };
 147    :  COMPILE_ASSERT_IS_POD_OF_SIZE(RecordPrefix, 16);
 148    :  
 149    :  // This structure is written at the beginning of a call trace file. If the
 150    :  // format of this trace file changes the server version must be increased.
 151    :  struct TraceFileHeader {
 152    :    // Everything in this header up to and including the header_size field should
 153    :    // not be changed in order, layout or alignment. This allows the beginning of
 154    :    // the header to be read across all trace file versions. If adding a new
 155    :    // fixed length field, do so immediately prior to blob_data. If adding a new
 156    :    // variable length field, append it to blob data updating the comment below,
 157    :    // and both the reading and writing of TraceFileHeader.
 158    :  
 159    :    // The "magic-number" identifying this as a Syzygy call-trace file.
 160    :    // In a valid trace file this will be "SZGY".
 161    :    typedef char Signature[4];
 162    :  
 163    :    // A canonical value for the signature.
 164    :    static const Signature kSignatureValue;
 165    :  
 166    :    // A signature is at the start of the trace file header.
 167    :    Signature signature;
 168    :  
 169    :    // The version of the call trace service which recorded this trace file.
 170    :    struct {
 171    :      uint16_t lo;
 172    :      uint16_t hi;
 173    :    } server_version;
 174    :  
 175    :    // The number of bytes in the header. This is the size of this structure
 176    :    // plus the length of the blob.
 177    :    uint32_t header_size;
 178    :  
 179    :    // Nothing above this point in the header can change in order to maintain
 180    :    // the ability to parse the basic header with the version number. This by
 181    :    // itself doesn't guarantee backwards compatibility, but it does ensure that
 182    :    // we can detect trace files generated by older versions of the toolchain.
 183    :  
 184    :    // The block size used when writing the file to disk. The header and
 185    :    // all segments are padded and byte aligned to this block size.
 186    :    uint32_t block_size;
 187    :  
 188    :    // The id of the process being traced.
 189    :    uint32_t process_id;
 190    :  
 191    :    // The base address at which the executable module was loaded when the
 192    :    // trace file was created.
 193    :    uint32_t module_base_address;
 194    :  
 195    :    // The size of the executable module.
 196    :    uint32_t module_size;
 197    :  
 198    :    // The checksum of the executable module.
 199    :    uint32_t module_checksum;
 200    :  
 201    :    // The timestamp of the executable module.
 202    :    uint32_t module_time_date_stamp;
 203    :  
 204    :    // System information.
 205    :    OSVERSIONINFOEX os_version_info;
 206    :    SYSTEM_INFO system_info;
 207    :    MEMORYSTATUSEX memory_status;
 208    :  
 209    :    // Clock information. This lets us convert from timestamps (both TSC and
 210    :    // ticks) to absolute system times. It also contains a timestamp for the
 211    :    // header itself.
 212    :    trace::common::ClockInfo clock_info;
 213    :  
 214    :    // The header is required to store multiple variable length fields. We do
 215    :    // this via a blob mechanism. The header contains a single binary blob at the
 216    :    // end, whose length in bytes) is encoded via blob_length.
 217    :    //
 218    :    // Currently, the header stores the following variable length fields (in
 219    :    // the order indicated):
 220    :    //
 221    :    //   1. The path to the instrumented module, a NULL terminated wide string.
 222    :    //   2. The command line for the process, a NULL terminated wide string.
 223    :    //   3. The environment string for the process, an array of wide chars
 224    :    //      terminated by a double NULL (individual environment variables are
 225    :    //      separated by single NULLs).
 226    :  
 227    :    // This stores the variable length data, concatenated. This should be pointer
 228    :    // aligned so that PODs with alignment constraints embedded in the blob can be
 229    :    // read directly from a header loaded into memory.
 230    :    uint8_t blob_data[1];
 231    :  };
 232    :  COMPILE_ASSERT_IS_POD(TraceFileHeader);
 233    :  
 234    :  // Written at the beginning of a call trace file segment. Each call trace file
 235    :  // segment has a length, which on-disk is rounded up to the block_size, as
 236    :  // recorded in the TraceFileHeader. Within a call trace segment, there are one
 237    :  // or more records, each prefixed with a RecordPrefix, which describes the
 238    :  // length and type of the data to follow.
 239    :  struct TraceFileSegmentHeader {
 240    :    // Type identifiers used for these headers.
 241    :    enum { kTypeId = TRACE_PAGE_HEADER };
 242    :  
 243    :    // The identity of the thread that is reporting in this segment
 244    :    // of the trace file.
 245    :    uint32_t thread_id;
 246    :  
 247    :    // The number of data bytes in this segment of the trace file. This
 248    :    // value does not include the size of the record prefix nor the size
 249    :    // of the segment header.
 250    :    uint32_t segment_length;
 251    :  };
 252    :  COMPILE_ASSERT_IS_POD(TraceFileSegmentHeader);
 253    :  
 254    :  // The structure traced on function entry or exit.
 255    :  template<int TypeId>
 256    :  struct TraceEnterExitEventDataTempl {
 257    :    enum { kTypeId = TypeId };
 258    :    RetAddr retaddr;
 259    :    FuncAddr function;
 260    :  };
 261    :  
 262    :  typedef TraceEnterExitEventDataTempl<TRACE_ENTER_EVENT> TraceEnterEventData;
 263    :  typedef TraceEnterExitEventDataTempl<TRACE_EXIT_EVENT> TraceExitEventData;
 264    :  typedef TraceEnterEventData TraceEnterExitEventData;
 265    :  COMPILE_ASSERT_IS_POD(TraceEnterEventData);
 266    :  COMPILE_ASSERT_IS_POD(TraceExitEventData);
 267    :  COMPILE_ASSERT_IS_POD(TraceEnterExitEventData);
 268    :  
 269    :  // The structure written for each loaded module when module event tracing is
 270    :  // enabled.
 271    :  struct TraceModuleData {
 272    :    ModuleAddr module_base_addr;
 273    :    size_t module_base_size;
 274    :    uint32_t module_checksum;
 275    :    uint32_t module_time_date_stamp;
 276    :    wchar_t module_name[256];
 277    :    wchar_t module_exe[MAX_PATH];
 278    :  };
 279    :  COMPILE_ASSERT_IS_POD(TraceModuleData);
 280    :  
 281    :  // This is for storing environment string information. Each environment string
 282    :  // consists of a pair of strings, the key and the value. Certain special
 283    :  // strings have empty keys.
 284  E :  typedef std::vector<std::pair<std::wstring, std::wstring>>
 285    :      TraceEnvironmentStrings;
 286    :  
 287    :  // Describes the system information and environment in which a process is
 288    :  // running.
 289    :  struct TraceSystemInfo {
 290    :    OSVERSIONINFOEX os_version_info;
 291    :    SYSTEM_INFO system_info;
 292    :    MEMORYSTATUSEX memory_status;
 293    :    trace::common::ClockInfo clock_info;
 294    :    TraceEnvironmentStrings environment_strings;
 295    :  };
 296    :  
 297    :  // The structure traced for batch entry traces.
 298    :  struct TraceBatchEnterData {
 299    :    enum { kTypeId = TRACE_BATCH_ENTER };
 300    :  
 301    :    // The thread ID from which these traces originate. This can differ
 302    :    // from the logging thread ID when a process exits, and the exiting
 303    :    // thread flushes the trace buffers from its expired brethren.
 304    :    DWORD thread_id;
 305    :  
 306    :    // Number of function entries.
 307    :    size_t num_calls;
 308    :  
 309    :    // Back-to-back entry events.
 310    :    TraceEnterEventData calls[1];
 311    :  };
 312    :  COMPILE_ASSERT_IS_POD(TraceBatchEnterData);
 313    :  
 314    :  enum InvocationInfoFlags {
 315    :    // If this bit is set in InvocationInfo flags, the caller is a dynamic
 316    :    // symbol id, and caller_offset is the offset of the return site, relative to
 317    :    // the start of the caller's symbol.
 318    :    kCallerIsSymbol = 0x01,
 319    :    // If this bit is set in InvocationInfo flags, the function is a dynamic
 320    :    // symbol id, instead of an address.
 321    :    kFunctionIsSymbol = 0x02,
 322    :  };
 323    :  
 324    :  // This is the data recorded for each distinct caller/function
 325    :  // pair by the profiler.
 326    :  struct InvocationInfo {
 327    :    union {
 328    :      RetAddr caller;
 329    :      uint32_t caller_symbol_id;
 330    :    };
 331    :    union {
 332    :      FuncAddr function;
 333    :      uint32_t function_symbol_id;
 334    :    };
 335    :    size_t num_calls;
 336    :    uint32_t flags : 8;
 337    :    uint32_t caller_offset : 24;
 338    :    uint64_t cycles_min;
 339    :    uint64_t cycles_max;
 340    :    uint64_t cycles_sum;
 341    :  };
 342    :  COMPILE_ASSERT_IS_POD(InvocationInfo);
 343    :  
 344    :  struct TraceBatchInvocationInfo {
 345    :    enum { kTypeId = TRACE_BATCH_INVOCATION };
 346    :  
 347    :    // TODO(siggi): Perhaps the batch should carry the time resolution for
 348    :    //    the invocation data?
 349    :  
 350    :    // Back to back entries, as many as our enclosing record's size allows for.
 351    :    InvocationInfo invocations[1];
 352    :  };
 353    :  COMPILE_ASSERT_IS_POD(TraceBatchInvocationInfo);
 354    :  
 355    :  struct TraceThreadNameInfo {
 356    :    enum { kTypeId = TRACE_THREAD_NAME };
 357    :    // In fact as many as our enclosing record's size allows for,
 358    :    // zero terminated.
 359    :    char thread_name[1];
 360    :  };
 361    :  COMPILE_ASSERT_IS_POD(TraceThreadNameInfo);
 362    :  
 363    :  struct TraceIndexedFrequencyData {
 364    :    enum { kTypeId = TRACE_INDEXED_FREQUENCY };
 365    :  
 366    :    // This is used to tie the data to a particular module, which has already
 367    :    // been reported via a TraceModuleData struct.
 368    :    ModuleAddr module_base_addr;
 369    :    size_t module_base_size;
 370    :    uint32_t module_checksum;
 371    :    uint32_t module_time_date_stamp;
 372    :  
 373    :    // The number of entries being reported. It is up to the instrumentation to
 374    :    // output any other metadata that is required to map an index to an address.
 375    :    uint32_t num_entries;
 376    :  
 377    :    // The number of columns for each record. Each column entry has the data sized
 378    :    // specified by |frequency_size|.
 379    :    uint32_t num_columns;
 380    :  
 381    :    // The type of data contained in this frequency record. This should be one of
 382    :    // the data-types defined in IndexedFrequencyData::DataType.
 383    :    uint8_t data_type;
 384    :  
 385    :    // The size of the frequency reports: 1, 2 or 4 bytes.
 386    :    uint8_t frequency_size;
 387    :  
 388    :    // In fact, there are frequency_size * num_basic_blocks bytes that follow.
 389    :    uint8_t frequency_data[1];
 390    :  };
 391    :  COMPILE_ASSERT_IS_POD(TraceIndexedFrequencyData);
 392    :  
 393    :  struct TraceDynamicSymbol {
 394    :    enum { kTypeId = TRACE_DYNAMIC_SYMBOL };
 395    :  
 396    :    // The symbol's ID, unique per process.
 397    :    uint32_t symbol_id;
 398    :    // In fact as many as our enclosing record's size allows for,
 399    :    // zero terminated.
 400    :    char symbol_name[1];
 401    :  };
 402    :  COMPILE_ASSERT_IS_POD(TraceDynamicSymbol);
 403    :  
 404    :  struct TraceSampleData {
 405    :    enum { kTypeId = TRACE_SAMPLE_DATA };
 406    :  
 407    :    // This is used to tie the data to a particular module, which has already
 408    :    // been reported via a TraceModuleData struct.
 409    :    ModuleAddr module_base_addr;
 410    :    size_t module_size;
 411    :    uint32_t module_checksum;
 412    :    uint32_t module_time_date_stamp;
 413    :  
 414    :    // The size of each bucket in the sample data. This will be a power of 2 in
 415    :    // size.
 416    :    uint32_t bucket_size;
 417    :  
 418    :    // The beginning of the sampling buckets as an address in the image.
 419    :    // This will be aligned with the bucket size.
 420    :    ModuleAddr bucket_start;
 421    :  
 422    :    // The number of buckets in the sample data.
 423    :    uint32_t bucket_count;
 424    :  
 425    :    // The time when the trace started and ended.
 426    :    uint64_t sampling_start_time;
 427    :    uint64_t sampling_end_time;
 428    :  
 429    :    // The sampling interval, expressed in clock cycles.
 430    :    uint64_t sampling_interval;
 431    :  
 432    :    // There are actually |bucket_count| buckets that follow.
 433    :    uint32_t buckets[1];
 434    :  };
 435    :  COMPILE_ASSERT_IS_POD(TraceSampleData);
 436    :  
 437    :  // Records a functions name and its assined ID.
 438    :  struct TraceFunctionNameTableEntry {
 439    :    enum { kTypeId = TRACE_FUNCTION_NAME_TABLE_ENTRY };
 440    :  
 441    :    // The assigned ID of this function.
 442    :    uint32_t function_id;
 443    :  
 444    :    // The length of the function name.
 445    :    uint32_t name_length;
 446    :  
 447    :    // The name of this function. This is actually of length |name_length|,
 448    :    // which doesn't need to include null termination.
 449    :    char name[1];
 450    :  };
 451    :  COMPILE_ASSERT_IS_POD(TraceFunctionNameTableEntry);
 452    :  
 453    :  // Records an unsymbolized stack trace. This is referred to by other
 454    :  // records, which put it in appropriate context.
 455    :  struct TraceStackTrace {
 456    :    enum { kTypeId = TRACE_STACK_TRACE };
 457    :  
 458    :    // The ID of this stack trace. This is computed as a hash of the stack trace
 459    :    // and is unique for a given set of load addresses (ie: for a process).
 460    :    uint32_t stack_trace_id;
 461    :  
 462    :    // The number of frames in the stack trace.
 463    :    uint32_t num_frames;
 464    :  
 465    :    // The frames of the stack trace. There are actually |num_frames| frames
 466    :    // in total.
 467    :    void* frames[1];
 468    :  };
 469    :  
 470    :  // Records detailed information about a call to a function.
 471    :  struct TraceDetailedFunctionCall {
 472    :    enum { kTypeId = TRACE_DETAILED_FUNCTION_CALL };
 473    :  
 474    :    // The timestamp of the funtion call.
 475    :    uint64_t timestamp;
 476    :  
 477    :    // The ID of the function. This is an entry in the global
 478    :    // function table.
 479    :    uint32_t function_id;
 480    :  
 481    :    // The ID of the stack trace leading to the function call.
 482    :    uint32_t stack_trace_id;
 483    :  
 484    :    // The size of the argument data.
 485    :    uint32_t argument_data_size;
 486    :  
 487    :    // The blob of argument data. This is actually of size
 488    :    // |argument_data_size|. This is laid out as follows:
 489    :    // uint32_t argument_count
 490    :    // uint32_t argument_length_0
 491    :    // uint32_t argument_length_1
 492    :    // ...
 493    :    // uint8_t argument_data_0
 494    :    // uint8_t argument_data_1
 495    :    // ...
 496    :    // The content and interpretation of this data is up to the
 497    :    // individual producer and consumer.
 498    :    uint8_t argument_data[1];
 499    :  };
 500    :  COMPILE_ASSERT_IS_POD(TraceDetailedFunctionCall);
 501    :  
 502    :  // Records a comment in a trace file. These are output via the call-trace
 503    :  // service and act as delimiters in a call-trace log.
 504    :  struct TraceComment {
 505    :    enum { kTypedId = TRACE_COMMENT };
 506    :  
 507    :    // The size of the comment in bytes.
 508    :    uint32_t comment_size;
 509    :  
 510    :    // Actually of size |comment_size|. A UTF8 encoded string.
 511    :    char comment[1];
 512    :  };
 513    :  
 514    :  // Records the address of the process heap.
 515    :  struct TraceProcessHeap {
 516    :    enum { kTypeId = TRACE_PROCESS_HEAP };
 517    :  
 518    :    uint32_t process_heap;
 519    :  };
 520    :  COMPILE_ASSERT_IS_POD(TraceProcessHeap);
 521    :  
 522    :  #endif  // SYZYGY_TRACE_PROTOCOL_CALL_TRACE_DEFS_H_

Coverage information generated Fri Jul 29 11:00:21 2016.