private unsafe void SlowLookup(EVENT_RECORD *eventRecord, EventRecordReader eventRecordReader, RuntimeEventMetadata runtimeMetadata, ref TraceEventKey key) { if (this.CustomParserLookup(eventRecord, ref key)) { return; } bool isSpecialKernelTraceMetaDataEvent = false; var operand = this.BuildOperand(eventRecord, eventRecordReader, this.eventMetadataTableList.Count, ref isSpecialKernelTraceMetaDataEvent); if (operand != null) { this.eventMetadataTableList.Add(operand.Metadata); this.eventMetadataTable = this.eventMetadataTableList.ToArray(); // TODO: Need to improve this var eventRecordReaderParam = Expression.Parameter(ReaderType); var eventWriterParam = Expression.Parameter(WriterType); var eventMetadataTableParam = Expression.Parameter(EventMetadataArrayType); var runtimeMetadataParam = Expression.Parameter(RuntimeMetadataType); var parameters = new[] { eventRecordReaderParam, eventWriterParam, eventMetadataTableParam, runtimeMetadataParam }; var name = Regex.Replace(InvalidCharacters.Replace(operand.Metadata.Name, "_"), @"\s+", "_"); var body = EventTraceOperandExpressionBuilder.Build(operand, eventRecordReaderParam, eventWriterParam, eventMetadataTableParam, runtimeMetadataParam); LambdaExpression expression = Expression.Lambda <Action <EventRecordReader, T, EventMetadata[], RuntimeEventMetadata> >(body, "Read_" + name, parameters); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.RunAndCollect); var moduleBuilder = assemblyBuilder.DefineDynamicModule(name, name + ".dll"); var typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public); var methodBuilder = typeBuilder.DefineMethod("Read", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new[] { ReaderType, WriterType, EventMetadataArrayType, RuntimeMetadataType }); expression.CompileToMethod(methodBuilder); var action = (Action <EventRecordReader, T, EventMetadata[], RuntimeEventMetadata>)Delegate.CreateDelegate(expression.Type, typeBuilder.CreateType().GetMethod("Read")); if (isSpecialKernelTraceMetaDataEvent) { var e = (TRACE_EVENT_INFO *)eventRecord->UserDataFixed; this.actionTable.AddOrUpdate(new TraceEventKey(e->ProviderGuid, e->EventGuid == Guid.Empty ? e->Id : e->Opcode, e->Version), action); } else { this.actionTable.Add(key, action); action(eventRecordReader, this.writer, this.eventMetadataTable, runtimeMetadata); } } }
public unsafe void Deserialize(EVENT_RECORD *eventRecord) { eventRecord->UserDataFixed = eventRecord->UserData; var eventRecordReader = new EventRecordReader(eventRecord); var runtimeMetadata = new RuntimeEventMetadata(eventRecord); var key = new TraceEventKey( eventRecord->ProviderId, (eventRecord->Flags & Etw.EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0 ? eventRecord->Opcode : eventRecord->Id, eventRecord->Version); Action <EventRecordReader, T, EventMetadata[], RuntimeEventMetadata> action; if (this.actionTable.TryGetValue(key, out action)) { action(eventRecordReader, this.writer, this.eventMetadataTable, runtimeMetadata); } else { this.SlowLookup(eventRecord, eventRecordReader, runtimeMetadata, ref key); } }
private unsafe IEventTraceOperand BuildOperand(EVENT_RECORD *eventRecord, EventRecordReader eventRecordReader, int metadataTableIndex, ref bool isSpecialKernelTraceMetaDataEvent) { if (eventRecord->ProviderId == CustomParserGuids.KernelTraceControlMetaDataGuid && eventRecord->Opcode == 32) { isSpecialKernelTraceMetaDataEvent = true; return(EventTraceOperandBuilder.Build((TRACE_EVENT_INFO *)eventRecord->UserData, metadataTableIndex)); } IEventTraceOperand operand; if ((operand = BuildOperandFromTdh(eventRecord, metadataTableIndex)) == null) { operand = BuildOperandFromXml(eventRecord, this.eventSourceManifestCache, eventRecordReader, metadataTableIndex); } if (operand == null && eventRecord->Id != 65534) // don't show manifest events { operand = BuildUnknownOperand(eventRecord, metadataTableIndex); } return(operand); }
private unsafe void SlowLookup(EVENT_RECORD *eventRecord, EventRecordReader eventRecordReader, RuntimeEventMetadata runtimeMetadata, ref TraceEventKey key) { if (this.CustomParserLookup(eventRecord, ref key)) { return; } bool isSpecialKernelTraceMetaDataEvent = false; var operand = this.BuildOperand(eventRecord, eventRecordReader, this.eventMetadataTableList.Count, ref isSpecialKernelTraceMetaDataEvent); if (operand != null) { this.eventMetadataTableList.Add(operand.Metadata); this.eventMetadataTable = this.eventMetadataTableList.ToArray(); // TODO: Need to improve this var eventRecordReaderParam = Expression.Parameter(ReaderType); var eventWriterParam = Expression.Parameter(WriterType); var eventMetadataTableParam = Expression.Parameter(EventMetadataArrayType); var runtimeMetadataParam = Expression.Parameter(RuntimeMetadataType); var parameters = new[] { eventRecordReaderParam, eventWriterParam, eventMetadataTableParam, runtimeMetadataParam }; var name = Regex.Replace(InvalidCharacters.Replace(operand.Metadata.Name, "_"), @"\s+", "_"); var body = EventTraceOperandExpressionBuilder.Build(operand, eventRecordReaderParam, eventWriterParam, eventMetadataTableParam, runtimeMetadataParam); LambdaExpression expression = Expression.Lambda <Action <EventRecordReader, T, EventMetadata[], RuntimeEventMetadata> >(body, "Read_" + name, parameters); var action = (Action <EventRecordReader, T, EventMetadata[], RuntimeEventMetadata>)expression.Compile(false); if (isSpecialKernelTraceMetaDataEvent) { var e = (TRACE_EVENT_INFO *)eventRecord->UserDataFixed; this.actionTable.AddOrUpdate(new TraceEventKey(e->ProviderGuid, e->EventGuid == Guid.Empty ? e->Id : e->Opcode, e->Version), action); } else { this.actionTable.Add(key, action); action(eventRecordReader, this.writer, this.eventMetadataTable, runtimeMetadata); } } }
private static unsafe IEventTraceOperand BuildOperandFromXml(EVENT_RECORD *eventRecord, Dictionary <Guid, EventSourceManifest> cache, EventRecordReader eventRecordReader, int metadataTableIndex) { EventSourceManifest manifest; Guid providerGuid = eventRecord->ProviderId; if (!cache.TryGetValue(providerGuid, out manifest)) { manifest = CreateEventSourceManifest(providerGuid, cache, eventRecord, eventRecordReader); } if (manifest == null) { return(null); } return(!manifest.IsComplete ? null : EventTraceOperandBuilder.Build(manifest.Schema, eventRecord->Id, metadataTableIndex)); }
private static unsafe EventSourceManifest CreateEventSourceManifest(Guid providerGuid, Dictionary <Guid, EventSourceManifest> cache, EVENT_RECORD *eventRecord, EventRecordReader eventRecordReader) { // EventSource Schema events have the following signature: // { byte Format, byte MajorVersion, byte MinorVersion, byte Magic, ushort TotalChunks, ushort ChunkNumber } == 8 bytes, followed by the XML schema if (eventRecord->UserDataLength <= 8) { return(null); } var format = eventRecordReader.ReadUInt8(); var majorVersion = eventRecordReader.ReadUInt8(); var minorVersion = eventRecordReader.ReadUInt8(); var magic = eventRecordReader.ReadUInt8(); ushort totalChunks = eventRecordReader.ReadUInt16(); ushort chunkNumber = eventRecordReader.ReadUInt16(); if (!(format == 1 && magic == 0x5B)) { return(null); } EventSourceManifest manifest; if (!cache.TryGetValue(providerGuid, out manifest)) { manifest = new EventSourceManifest(eventRecord->ProviderId, format, majorVersion, minorVersion, magic, totalChunks); cache.Add(providerGuid, manifest); } // if manifest is complete, maybe the data changed? ideally version should have changed // this is essentially a reset if (manifest.IsComplete && chunkNumber == 0) { cache[providerGuid] = manifest; } string schemaChunk = eventRecordReader.ReadAnsiString(); manifest.AddChunk(schemaChunk); return(manifest); }