1<!DOCTYPE html> 2<!-- 3Copyright (c) 2014 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="import" href="/tracing/extras/importer/etw/parser.html"> 9 10<script> 11'use strict'; 12 13/** 14 * @fileoverview Parses processes events in the Windows event trace format. 15 * 16 * The Windows process events are: 17 * 18 * - DCStart: Describes a process that was already running when the trace 19 * started. ETW automatically generates these events for all running 20 * processes at the beginning of the trace. 21 * - Start: Describes a process launched during the tracing session. 22 * - End: Describes a process that ended during the tracing session. 23 * - DCEnd: Describes a process that was still running when the trace ended. 24 * 25 * See http://msdn.microsoft.com/library/windows/desktop/aa364092.aspx 26 */ 27tr.exportTo('tr.e.importer.etw', function() { 28 var Parser = tr.e.importer.etw.Parser; 29 30 // Constants for Process events. 31 var guid = '3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C'; 32 var kProcessStartOpcode = 1; 33 var kProcessEndOpcode = 2; 34 var kProcessDCStartOpcode = 3; 35 var kProcessDCEndOpcode = 4; 36 var kProcessDefunctOpcode = 39; 37 38 /** 39 * Parses Windows process trace events. 40 * @constructor 41 */ 42 function ProcessParser(importer) { 43 Parser.call(this, importer); 44 45 // Register handlers. 46 importer.registerEventHandler(guid, kProcessStartOpcode, 47 ProcessParser.prototype.decodeStart.bind(this)); 48 importer.registerEventHandler(guid, kProcessEndOpcode, 49 ProcessParser.prototype.decodeEnd.bind(this)); 50 importer.registerEventHandler(guid, kProcessDCStartOpcode, 51 ProcessParser.prototype.decodeDCStart.bind(this)); 52 importer.registerEventHandler(guid, kProcessDCEndOpcode, 53 ProcessParser.prototype.decodeDCEnd.bind(this)); 54 importer.registerEventHandler(guid, kProcessDefunctOpcode, 55 ProcessParser.prototype.decodeDefunct.bind(this)); 56 } 57 58 ProcessParser.prototype = { 59 __proto__: Parser.prototype, 60 61 decodeFields: function(header, decoder) { 62 if (header.version > 5) 63 throw new Error('Incompatible Process event version.'); 64 65 var pageDirectoryBase; 66 if (header.version == 1) 67 pageDirectoryBase = decoder.decodeUInteger(header.is64); 68 69 var uniqueProcessKey; 70 if (header.version >= 2) 71 uniqueProcessKey = decoder.decodeUInteger(header.is64); 72 73 var processId = decoder.decodeUInt32(); 74 var parentId = decoder.decodeUInt32(); 75 76 var sessionId; 77 var exitStatus; 78 if (header.version >= 1) { 79 sessionId = decoder.decodeUInt32(); 80 exitStatus = decoder.decodeInt32(); 81 } 82 83 var directoryTableBase; 84 if (header.version >= 3) 85 directoryTableBase = decoder.decodeUInteger(header.is64); 86 87 var flags; 88 if (header.version >= 4) 89 flags = decoder.decodeUInt32(); 90 91 var userSID = decoder.decodeSID(header.is64); 92 93 var imageFileName; 94 if (header.version >= 1) 95 imageFileName = decoder.decodeString(); 96 97 var commandLine; 98 if (header.version >= 2) 99 commandLine = decoder.decodeW16String(); 100 101 var packageFullName; 102 var applicationId; 103 if (header.version >= 4) { 104 packageFullName = decoder.decodeW16String(); 105 applicationId = decoder.decodeW16String(); 106 } 107 108 var exitTime; 109 if (header.version == 5 && header.opcode == kProcessDefunctOpcode) 110 exitTime = decoder.decodeUInt64ToString(); 111 112 return { 113 pageDirectoryBase: pageDirectoryBase, 114 uniqueProcessKey: uniqueProcessKey, 115 processId: processId, 116 parentId: parentId, 117 sessionId: sessionId, 118 exitStatus: exitStatus, 119 directoryTableBase: directoryTableBase, 120 flags: flags, 121 userSID: userSID, 122 imageFileName: imageFileName, 123 commandLine: commandLine, 124 packageFullName: packageFullName, 125 applicationId: applicationId, 126 exitTime: exitTime 127 }; 128 }, 129 130 decodeStart: function(header, decoder) { 131 var fields = this.decodeFields(header, decoder); 132 var process = this.model.getOrCreateProcess(fields.processId); 133 if (process.hasOwnProperty('has_ended')) { 134 // On Windows, a process ID used by a process could be reused as soon as 135 // the process ends (there is no pid cycling like on Linux). However, in 136 // a short trace, this is unlikely to happen. 137 throw new Error('Process clash detected.'); 138 } 139 process.name = fields.imageFileName; 140 return true; 141 }, 142 143 decodeEnd: function(header, decoder) { 144 var fields = this.decodeFields(header, decoder); 145 var process = this.model.getOrCreateProcess(fields.processId); 146 process.has_ended = true; 147 return true; 148 }, 149 150 decodeDCStart: function(header, decoder) { 151 var fields = this.decodeFields(header, decoder); 152 var process = this.model.getOrCreateProcess(fields.processId); 153 if (process.hasOwnProperty('has_ended')) 154 throw new Error('Process clash detected.'); 155 process.name = fields.imageFileName; 156 return true; 157 }, 158 159 decodeDCEnd: function(header, decoder) { 160 var fields = this.decodeFields(header, decoder); 161 var process = this.model.getOrCreateProcess(fields.processId); 162 process.has_ended = true; 163 return true; 164 }, 165 166 decodeDefunct: function(header, decoder) { 167 var fields = this.decodeFields(header, decoder); 168 // TODO(etienneb): Update the Model with |fields|. 169 return true; 170 } 171 172 }; 173 174 Parser.register(ProcessParser); 175 176 return { 177 ProcessParser: ProcessParser 178 }; 179}); 180</script> 181 182