blob: 3f6dc324a794172cc3d71c842245b1f1a188b8a6 [file] [log] [blame]
<!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="/extras/importer/etw/parser.html">
<script>
'use strict';
/**
* @fileoverview Parses processes events in the Windows event trace format.
*
* The Windows process events are:
*
* - DCStart: Describes a process that was already running when the trace
* started. ETW automatically generates these events for all running
* processes at the beginning of the trace.
* - Start: Describes a process launched during the tracing session.
* - End: Describes a process that ended during the tracing session.
* - DCEnd: Describes a process that was still running when the trace ended.
*
* See http://msdn.microsoft.com/library/windows/desktop/aa364092.aspx
*/
tr.exportTo('tr.e.importer.etw', function() {
var Parser = tr.e.importer.etw.Parser;
// Constants for Process events.
var guid = '3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C';
var kProcessStartOpcode = 1;
var kProcessEndOpcode = 2;
var kProcessDCStartOpcode = 3;
var kProcessDCEndOpcode = 4;
var kProcessDefunctOpcode = 39;
/**
* Parses Windows process trace events.
* @constructor
*/
function ProcessParser(importer) {
Parser.call(this, importer);
// Register handlers.
importer.registerEventHandler(guid, kProcessStartOpcode,
ProcessParser.prototype.decodeStart.bind(this));
importer.registerEventHandler(guid, kProcessEndOpcode,
ProcessParser.prototype.decodeEnd.bind(this));
importer.registerEventHandler(guid, kProcessDCStartOpcode,
ProcessParser.prototype.decodeDCStart.bind(this));
importer.registerEventHandler(guid, kProcessDCEndOpcode,
ProcessParser.prototype.decodeDCEnd.bind(this));
importer.registerEventHandler(guid, kProcessDefunctOpcode,
ProcessParser.prototype.decodeDefunct.bind(this));
}
ProcessParser.prototype = {
__proto__: Parser.prototype,
decodeFields: function(header, decoder) {
if (header.version > 5)
throw new Error('Incompatible Process event version.');
var pageDirectoryBase;
if (header.version == 1)
pageDirectoryBase = decoder.decodeUInteger(header.is64);
var uniqueProcessKey;
if (header.version >= 2)
uniqueProcessKey = decoder.decodeUInteger(header.is64);
var processId = decoder.decodeUInt32();
var parentId = decoder.decodeUInt32();
var sessionId;
var exitStatus;
if (header.version >= 1) {
sessionId = decoder.decodeUInt32();
exitStatus = decoder.decodeInt32();
}
var directoryTableBase;
if (header.version >= 3)
directoryTableBase = decoder.decodeUInteger(header.is64);
var flags;
if (header.version >= 4)
flags = decoder.decodeUInt32();
var userSID = decoder.decodeSID(header.is64);
var imageFileName;
if (header.version >= 1)
imageFileName = decoder.decodeString();
var commandLine;
if (header.version >= 2)
commandLine = decoder.decodeW16String();
var packageFullName;
var applicationId;
if (header.version >= 4) {
packageFullName = decoder.decodeW16String();
applicationId = decoder.decodeW16String();
}
var exitTime;
if (header.version == 5 && header.opcode == kProcessDefunctOpcode)
exitTime = decoder.decodeUInt64ToString();
return {
pageDirectoryBase: pageDirectoryBase,
uniqueProcessKey: uniqueProcessKey,
processId: processId,
parentId: parentId,
sessionId: sessionId,
exitStatus: exitStatus,
directoryTableBase: directoryTableBase,
flags: flags,
userSID: userSID,
imageFileName: imageFileName,
commandLine: commandLine,
packageFullName: packageFullName,
applicationId: applicationId,
exitTime: exitTime
};
},
decodeStart: function(header, decoder) {
var fields = this.decodeFields(header, decoder);
var process = this.model.getOrCreateProcess(fields.processId);
if (process.hasOwnProperty('has_ended')) {
// On Windows, a process ID used by a process could be reused as soon as
// the process ends (there is no pid cycling like on Linux). However, in
// a short trace, this is unlikely to happen.
throw new Error('Process clash detected.');
}
process.name = fields.imageFileName;
return true;
},
decodeEnd: function(header, decoder) {
var fields = this.decodeFields(header, decoder);
var process = this.model.getOrCreateProcess(fields.processId);
process.has_ended = true;
return true;
},
decodeDCStart: function(header, decoder) {
var fields = this.decodeFields(header, decoder);
var process = this.model.getOrCreateProcess(fields.processId);
if (process.hasOwnProperty('has_ended'))
throw new Error('Process clash detected.');
process.name = fields.imageFileName;
return true;
},
decodeDCEnd: function(header, decoder) {
var fields = this.decodeFields(header, decoder);
var process = this.model.getOrCreateProcess(fields.processId);
process.has_ended = true;
return true;
},
decodeDefunct: function(header, decoder) {
var fields = this.decodeFields(header, decoder);
// TODO(etienneb): Update the Model with |fields|.
return true;
}
};
Parser.register(ProcessParser);
return {
ProcessParser: ProcessParser
};
});
</script>