<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="/tracing/extras/importer/etw/eventtrace_parser.html">
<link rel="import" href="/tracing/extras/importer/etw/process_parser.html">
<link rel="import" href="/tracing/extras/importer/etw/thread_parser.html">
<link rel="import" href="/tracing/importer/importer.html">
<link rel="import" href="/tracing/base/base64.html">
<link rel="import" href="/tracing/model/model.html">

<script>
/**
 * @fileoverview Imports JSON file with the raw payloads from a Windows event
 * trace into the Model. This format is outputted by Chrome running
 * on a Windows system.
 *
 * This importer assumes the events arrived as a JSON file and the payloads are
 * undecoded sequence of bytes in hex format string. The unit tests provide
 * examples of the trace format.
 *
 * The format of the system trace is
 *     {
 *       name: 'ETW',
 *       content: [ <events> ]
 *     }
  *
 * where the <events> are dictionary values with fields.
 *
 *     {
 *       guid: "1234-...",    // The unique GUID for the event.
 *       op: 12,              // The opcode of the event.
 *       ver: 1,              // The encoding version of the event.
 *       cpu: 0,              // The cpu id on which the event was captured.
 *       ts: 1092,            // The thread id on which the event was captured.
 *       payload: "aaaa"      // A base64 encoded string of the raw payload.
 *     }
 *
 * The payload is an undecoded version of the raw event sent by ETW.
 * This importer uses specific parsers to decode recognized events.
 * A parser need to register the recognized event by calling
 * registerEventHandler(guid, opcode, handler). The parser is responsible to
 * decode the payload and update the Model.
 *
 * The payload formats are described there:
 *   http://msdn.microsoft.com/en-us/library/windows/desktop/aa364085(v=vs.85).aspx
 *
 */
'use strict';

tr.exportTo('tr.e.importer.etw', function() {
  // GUID and opcode of a Thread DCStart event, as defined at the link above.
  var kThreadGuid = '3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';
  var kThreadDCStartOpcode = 3;

  /**
   * Represents the raw bytes payload decoder.
   * @constructor
   */
  function Decoder() {
    this.payload_ = new DataView(new ArrayBuffer(256));
  };

  Decoder.prototype = {
    __proto__: Object.prototype,

    reset: function(base64_payload) {
      var decoded_size = tr.b.Base64.getDecodedBufferLength(base64_payload);
      if (decoded_size > this.payload_.byteLength)
        this.payload_ = new DataView(new ArrayBuffer(decoded_size));

      tr.b.Base64.DecodeToTypedArray(base64_payload, this.payload_);
      this.position_ = 0;
    },

    skip: function(length) {
      this.position_ += length;
    },

    decodeUInt8: function() {
      var result = this.payload_.getUint8(this.position_, true);
      this.position_ += 1;
      return result;
    },

    decodeUInt16: function() {
      var result = this.payload_.getUint16(this.position_, true);
      this.position_ += 2;
      return result;
    },

    decodeUInt32: function() {
      var result = this.payload_.getUint32(this.position_, true);
      this.position_ += 4;
      return result;
    },

    decodeUInt64ToString: function() {
      // Javascript isn't able to manage 64-bit numeric values.
      var low = this.decodeUInt32();
      var high = this.decodeUInt32();
      var low_str = ('0000000' + low.toString(16)).substr(-8);
      var high_str = ('0000000' + high.toString(16)).substr(-8);
      var result = high_str + low_str;
      return result;
    },

    decodeInt8: function() {
      var result = this.payload_.getInt8(this.position_, true);
      this.position_ += 1;
      return result;
    },

    decodeInt16: function() {
      var result = this.payload_.getInt16(this.position_, true);
      this.position_ += 2;
      return result;
    },

    decodeInt32: function() {
      var result = this.payload_.getInt32(this.position_, true);
      this.position_ += 4;
      return result;
    },

    decodeInt64ToString: function() {
      // Javascript isn't able to manage 64-bit numeric values.
      // Fallback to unsigned 64-bit hexa value.
      return this.decodeUInt64ToString();
    },

    decodeUInteger: function(is64) {
      if (is64)
        return this.decodeUInt64ToString();
      return this.decodeUInt32();
    },

    decodeString: function() {
      var str = '';
      while (true) {
        var c = this.decodeUInt8();
        if (!c)
          return str;
        str = str + String.fromCharCode(c);
      }
    },

    decodeW16String: function() {
      var str = '';
      while (true) {
        var c = this.decodeUInt16();
        if (!c)
          return str;
        str = str + String.fromCharCode(c);
      }
    },

    decodeFixedW16String: function(length) {
      var old_position = this.position_;
      var str = '';
      for (var i = 0; i < length; i++) {
        var c = this.decodeUInt16();
        if (!c)
          break;
        str = str + String.fromCharCode(c);
      }

      // Move the position after the fixed buffer (i.e. wchar[length]).
      this.position_ = old_position + 2 * length;
      return str;
    },

    decodeBytes: function(length) {
      var bytes = [];
      for (var i = 0; i < length; ++i) {
        var c = this.decodeUInt8();
        bytes.push(c);
      }
      return bytes;
    },

    decodeSID: function(is64) {
      // Decode the TOKEN_USER structure.
      var pSid = this.decodeUInteger(is64);
      var attributes = this.decodeUInt32();

      // Skip padding.
      if (is64)
        this.decodeUInt32();

      // Decode the SID structure.
      var revision = this.decodeUInt8();
      var subAuthorityCount = this.decodeUInt8();
      this.decodeUInt16();
      this.decodeUInt32();

      if (revision != 1)
        throw 'Invalid SID revision: could not decode the SID structure.';

      var sid = this.decodeBytes(4 * subAuthorityCount);

      return {
        pSid: pSid,
        attributes: attributes,
        sid: sid
      };
    },

    decodeSystemTime: function() {
      // Decode the SystemTime structure.
      var wYear = this.decodeInt16();
      var wMonth = this.decodeInt16();
      var wDayOfWeek = this.decodeInt16();
      var wDay = this.decodeInt16();
      var wHour = this.decodeInt16();
      var wMinute = this.decodeInt16();
      var wSecond = this.decodeInt16();
      var wMilliseconds = this.decodeInt16();
      return {
        wYear: wYear,
        wMonth: wMonth,
        wDayOfWeek: wDayOfWeek,
        wDay: wDay,
        wHour: wHour,
        wMinute: wMinute,
        wSecond: wSecond,
        wMilliseconds: wMilliseconds
      };
    },

    decodeTimeZoneInformation: function() {
      // Decode the TimeZoneInformation structure.
      var bias = this.decodeUInt32();
      var standardName = this.decodeFixedW16String(32);
      var standardDate = this.decodeSystemTime();
      var standardBias = this.decodeUInt32();
      var daylightName = this.decodeFixedW16String(32);
      var daylightDate = this.decodeSystemTime();
      var daylightBias = this.decodeUInt32();
      return {
        bias: bias,
        standardName: standardName,
        standardDate: standardDate,
        standardBias: standardBias,
        daylightName: daylightName,
        daylightDate: daylightDate,
        daylightBias: daylightBias
      };
    }

  };

  /**
   * Imports Windows ETW kernel events into a specified model.
   * @constructor
   */
  function EtwImporter(model, events) {
    this.importPriority = 3;
    this.model_ = model;
    this.events_ = events;
    this.handlers_ = {};
    this.decoder_ = new Decoder();
    this.walltime_ = undefined;
    this.ticks_ = undefined;
    this.is64bit_ = undefined;

    // A map of tids to their process pid. On Windows, the tid is global to
    // the system and doesn't need to belong to a process. As many events
    // only provide tid, this map allows to retrieve the parent process.
    this.tidsToPid_ = {};

    // Instantiate the parsers; this will register handlers for known events.
    var allTypeInfos = tr.e.importer.etw.Parser.getAllRegisteredTypeInfos();
    this.parsers_ = allTypeInfos.map(
        function(typeInfo) {
          return new typeInfo.constructor(this);
        }, this);
  }

  /**
   * Guesses whether the provided events is from a Windows ETW trace.
   * The object must has a property named 'name' with the value 'ETW' and
   * a property 'content' with all the undecoded events.
   *
   * @return {boolean} True when events is a Windows ETW array.
   */
  EtwImporter.canImport = function(events) {
    if (!events.hasOwnProperty('name') ||
        !events.hasOwnProperty('content') ||
        events.name !== 'ETW') {
      return false;
    }

    return true;
  };

  EtwImporter.prototype = {
    __proto__: tr.importer.Importer.prototype,

    get model() {
      return this.model_;
    },

    createThreadIfNeeded: function(pid, tid) {
      this.tidsToPid_[tid] = pid;
    },

    removeThreadIfPresent: function(tid) {
      this.tidsToPid_[tid] = undefined;
    },

    getPidFromWindowsTid: function(tid) {
      if (tid == 0)
        return 0;
      var pid = this.tidsToPid_[tid];
      if (pid == undefined) {
        // Kernel threads are not defined.
        return 0;
      }
      return pid;
    },

    getThreadFromWindowsTid: function(tid) {
      var pid = this.getPidFromWindowsTid(tid);
      var process = this.model_.getProcess(pid);
      if (!process)
        return undefined;
      return process.getThread(tid);
    },

    /*
     * Retrieve the Cpu for a given cpuNumber.
     * @return {Cpu} A Cpu corresponding to the given cpuNumber.
     */
    getOrCreateCpu: function(cpuNumber) {
      var cpu = this.model_.kernel.getOrCreateCpu(cpuNumber);
      return cpu;
    },

    /**
     * Imports the data in this.events_ into this.model_.
     */
    importEvents: function(isSecondaryImport) {
      this.events_.content.forEach(this.parseInfo.bind(this));

      if (this.walltime_ == undefined || this.ticks_ == undefined)
        throw Error('Cannot find clock sync information in the system trace.');

      if (this.is64bit_ == undefined)
        throw Error('Cannot determine pointer size of the system trace.');

      this.events_.content.forEach(this.parseEvent.bind(this));
    },

    importTimestamp: function(timestamp) {
      var ts = parseInt(timestamp, 16);
      return (ts - this.walltime_ + this.ticks_) / 1000.;
    },

    parseInfo: function(event) {
      // Retrieve clock sync information.
      if (event.hasOwnProperty('guid') &&
          event.hasOwnProperty('walltime') &&
          event.hasOwnProperty('tick') &&
          event.guid === 'ClockSync') {
        this.walltime_ = parseInt(event.walltime, 16);
        this.ticks_ = parseInt(event.tick, 16);
      }

      // Retrieve pointer size information from a Thread.DCStart event.
      if (this.is64bit_ == undefined &&
          event.hasOwnProperty('guid') &&
          event.hasOwnProperty('op') &&
          event.hasOwnProperty('ver') &&
          event.hasOwnProperty('payload') &&
          event.guid === kThreadGuid &&
          event.op == kThreadDCStartOpcode) {
        var decoded_size = tr.b.Base64.getDecodedBufferLength(event.payload);

        if (event.ver == 1) {
          if (decoded_size >= 52)
            this.is64bit_ = true;
          else
            this.is64bit_ = false;
        } else if (event.ver == 2) {
          if (decoded_size >= 64)
            this.is64bit_ = true;
          else
            this.is64bit_ = false;
        } else if (event.ver == 3) {
          if (decoded_size >= 60)
            this.is64bit_ = true;
          else
            this.is64bit_ = false;
        }
      }

      return true;
    },

    parseEvent: function(event) {
      if (!event.hasOwnProperty('guid') ||
          !event.hasOwnProperty('op') ||
          !event.hasOwnProperty('ver') ||
          !event.hasOwnProperty('cpu') ||
          !event.hasOwnProperty('ts') ||
          !event.hasOwnProperty('payload')) {
        return false;
      }

      var timestamp = this.importTimestamp(event.ts);

      // Create the event header.
      var header = {
        guid: event.guid,
        opcode: event.op,
        version: event.ver,
        cpu: event.cpu,
        timestamp: timestamp,
        is64: this.is64bit_
      };

      // Set the payload to decode.
      var decoder = this.decoder_;
      decoder.reset(event.payload);

      // Retrieve the handler to decode the payload.
      var handler = this.getEventHandler(header.guid, header.opcode);
      if (!handler)
        return false;

      if (!handler(header, decoder)) {
        this.model_.importWarning({
          type: 'parse_error',
          message: 'Malformed ' + header.guid + ' event (' + text + ')'
        });
        return false;
      }

      return true;
    },

    /**
     * Registers a windows ETW event handler used by parseEvent().
     */
    registerEventHandler: function(guid, opcode, handler) {
      if (this.handlers_[guid] == undefined)
        this.handlers_[guid] = [];
      this.handlers_[guid][opcode] = handler;
    },

    /**
     * Retrieves a registered event handler.
     */
    getEventHandler: function(guid, opcode) {
      if (this.handlers_[guid] == undefined)
        return undefined;
      return this.handlers_[guid][opcode];
    }

  };

  // Register the EtwImporter to the Importer.
  tr.importer.Importer.register(EtwImporter);

  return {
    EtwImporter: EtwImporter
  };
});
</script>
