public unsafe void Deserialize(EVENT_RECORD *eventRecord) { if (eventRecord->Id == 65534 || bufferRead > bufferViewStart) { deserializer.Deserialize(eventRecord); } }
private unsafe void HandleModuleLoadEvent(EVENT_RECORD *eventRecord, byte *userData) { if (eventRecord->Version == 2) { var data = userData; ulong moduleId = ReadAlignedUInt64(ref data); var processModuleId = new ProcessModuleId(eventRecord->ProcessId, moduleId); if (!this.ManagedModuleInfoMap.ContainsKey(processModuleId)) { SkipUInt64(ref data); // assemblyId SkipUInt32(ref data); // moduleFlags SkipUInt32(ref data); // reserved string moduleILPath = ReadWideNullTerminatedString(ref data); string moduleNativePath = ReadWideNullTerminatedString(ref data); SkipUInt16(ref data); // clrInstanceId Guid managedSignature = ReadGuid(ref data); uint managedPdbAge = ReadUInt32(ref data); string managedPdbPath = ReadWideNullTerminatedString(ref data); Guid nativeSignature = ReadGuid(ref data); uint nativePdbAge = ReadUInt32(ref data); string nativePdbPath = ReadWideNullTerminatedString(ref data); this.ManagedModuleInfoMap.Add(processModuleId, new ManagedModuleInfo(moduleILPath, moduleNativePath, managedSignature, managedPdbAge, nativeSignature, nativePdbAge, managedPdbPath, nativePdbPath)); } } }
private unsafe void Deserialize2ndPass(EVENT_RECORD *eventRecord) { uint threadId = eventRecord->ThreadId; int pointerSize = (eventRecord->Flags & Etw.EVENT_HEADER_FLAG_64_BIT_HEADER) != 0 ? 8 : 4; if (eventRecord->ProviderId == SampleEvent && eventRecord->Opcode == 46) { threadId = *(uint *)(eventRecord->UserData + pointerSize); } if (this.samplesTimeStampMap.TryGetValue(new CorrelatedStackEvent(eventRecord->TimeStamp, threadId), out var index)) { var providerId = eventRecord->ProviderId; var eventId = (eventRecord->Flags & Etw.EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0 ? eventRecord->Opcode : eventRecord->Id; var key = new EtwProviderInfo(eventRecord->ProviderId, eventRecord->Id, eventRecord->Opcode); if (!this.etwProviderInfoMap.TryGetValue(key, out var stackEventType)) { var id = this.etwProviderInfoMapIndex++; stackEventType = new StackEventType(id, TdhGetManifestEventInformation(providerId, eventId)); this.etwProviderInfoMap.Add(key, stackEventType); this.EventStacks.Add(id, stackEventType); } stackEventType.SampleIndices.Add(index); } }
private unsafe void HandleMethodLoadEvent(EVENT_RECORD *eventRecord, byte *userData) { if (eventRecord->Version <= 2) { var data = userData; ulong methodId = ReadAlignedUInt64(ref data); ulong moduleId = ReadAlignedUInt64(ref data); ulong methodStartAddress = ReadAlignedUInt64(ref data); uint methodSize = ReadAlignedUInt32(ref data); uint methodToken = ReadAlignedUInt32(ref data); SkipUInt32(ref data); // method flags string methodNamespace = ReadWideNullTerminatedString(ref data); string methodName = ReadWideNullTerminatedString(ref data); string methodSignature = ReadWideNullTerminatedString(ref data); var methodInfo = new ManagedMethodInfo(methodToken, methodId, moduleId, methodStartAddress, methodStartAddress + methodSize, methodNamespace + "." + methodName + methodSignature.Substring(methodSignature.IndexOf('('))); uint pid = eventRecord->ProcessId; if (!this.MethodLoadMap.TryGetValue(pid, out List <ManagedMethodInfo> methodList)) { methodList = new List <ManagedMethodInfo>(); this.MethodLoadMap.Add(pid, methodList); } methodList.Add(methodInfo); } }
private unsafe void HandleImageLoadEvent(EVENT_RECORD *eventRecord, byte *userData, int pointerSize) { switch (eventRecord->Opcode) { case 3: // DCStart case 4: // DCStop case 10: // Load { var data = userData; ulong imageBase; uint size; uint pid; string imageFileName; switch (eventRecord->Version) { case 3: ImgLoadV3(ref data, pointerSize, out imageBase, out size, out pid, out imageFileName); break; case 2: ImgLoadV2(ref data, pointerSize, out imageBase, out size, out pid, out imageFileName); break; default: return; } if (!this.ImageLoadMap.TryGetValue(pid, out List <ImageInfo> imageList)) { imageList = new List <ImageInfo>(); this.ImageLoadMap.Add(pid, imageList); } bool duplicate = false; foreach (var t in imageList) { if (t.Begin == imageBase) { duplicate = true; break; } } if (!duplicate) { imageList.Add(new ImageInfo(imageBase, imageBase + size, imageFileName)); } break; } } }
private unsafe bool CustomParserLookup(EVENT_RECORD *eventRecord, ref TraceEventKey key) { bool success; // events added by KernelTraceControl.dll (i.e. Microsoft tools like WPR and PerfView) if (eventRecord->ProviderId == CustomParserGuids.KernelTraceControlImageIdGuid) { switch (eventRecord->Opcode) { case 0: this.actionTable.Add(key, new KernelTraceControlImageIdParser().Parse); success = true; break; case 36: this.actionTable.Add(key, new KernelTraceControlDbgIdParser().Parse); success = true; break; case 64: this.actionTable.Add(key, new KernelTraceControlImageIdFileVersionParser().Parse); success = true; break; default: success = false; break; } } // events by the Kernel Stack Walker (need this because the MOF events always says 32 stacks, but in reality there can be fewer or more else if (eventRecord->ProviderId == CustomParserGuids.KernelStackWalkGuid) { if (eventRecord->Opcode == 32) { this.actionTable.Add(key, new KernelStackWalkEventParser().Parse); success = true; } else { success = false; } } else { success = false; } return(success); }
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 unsafe void HandleExtendedData(EVENT_RECORD *eventRecord) { for (ushort i = 0; i < eventRecord->ExtendedDataCount; ++i) { if (eventRecord->ExtendedData[i].ExtType == Etw.EVENT_HEADER_EXT_TYPE_STACK_TRACE32) { int frameCount = (eventRecord->ExtendedData[i].DataSize - sizeof(ulong)) / sizeof(uint); this.HandleStacks((byte *)eventRecord->ExtendedData[i].DataPtr, frameCount, eventRecord->TimeStamp, 4, eventRecord->ProcessId, eventRecord->ThreadId); } if (eventRecord->ExtendedData[i].ExtType == Etw.EVENT_HEADER_EXT_TYPE_STACK_TRACE64) { int frameCount = (eventRecord->ExtendedData[i].DataSize - sizeof(ulong)) / sizeof(ulong); this.HandleStacks((byte *)eventRecord->ExtendedData[i].DataPtr + sizeof(ulong), frameCount, eventRecord->TimeStamp, 8, eventRecord->ProcessId, eventRecord->ThreadId); } } }
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); } } }
private unsafe void HandleDbgIdEvent(EVENT_RECORD *eventRecord, byte *userData, int pointerSize) { if (eventRecord->Opcode == 36 && eventRecord->Version == 2) { var data = userData; ulong imageBase = ReadAlignedPointer(ref data, pointerSize); var key = new ProcessImageId(eventRecord->ProcessId, imageBase); if (!this.ImageToDebugInfoMap.ContainsKey(key)) { SkipUInt32(ref data); // always ff ff var signature = ReadAlignedGuid(ref data); uint age = ReadAlignedUInt32(ref data); this.ImageToDebugInfoMap.Add(key, new DbgId(signature, age, Encoding.ASCII.GetString(data, eventRecord->UserDataLength - 32 - 1))); } } }
private static unsafe IEventTraceOperand BuildOperandFromTdh(EVENT_RECORD *eventRecord, int metadataTableIndex) { uint bufferSize; byte *buffer = (byte *)0; // Not Found if (Tdh.GetEventInformation(eventRecord, 0, IntPtr.Zero, buffer, out bufferSize) == 1168) { return(null); } buffer = (byte *)Marshal.AllocHGlobal((int)bufferSize); Tdh.GetEventInformation(eventRecord, 0, IntPtr.Zero, buffer, out bufferSize); var traceEventInfo = (TRACE_EVENT_INFO *)buffer; IEventTraceOperand traceEventOperand = EventTraceOperandBuilder.Build(traceEventInfo, metadataTableIndex); Marshal.FreeHGlobal((IntPtr)buffer); return(traceEventOperand); }
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); }
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 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 unsafe void HandleProcessEvents(EVENT_RECORD *eventRecord, byte *userData, int pointerSize) { switch (eventRecord->Opcode) { case 1: // Start case 3: // DCStart case 4: // DCStop { uint pid; string imageFileName; var data = userData; switch (eventRecord->Version) { case 4: ProcessInfoEventV4(ref data, pointerSize, out pid, out imageFileName); break; case 3: ProcessInfoEventV3(ref data, pointerSize, out pid, out imageFileName); break; default: return; } // TODO: BUG: yes, it turns out we can pid exiting and starting and so it's possible this will be broken but is good enough if (!this.ProcessIdToNameMap.ContainsKey(pid)) { this.ProcessIdToNameMap.Add(pid, imageFileName); } break; } } }
internal unsafe EventRecordReader(EVENT_RECORD *eventRecord) { this.eventRecord = eventRecord; }
internal unsafe RuntimeEventMetadata(EVENT_RECORD* eventRecord) { this.eventRecord = eventRecord; }
internal static extern unsafe int GetEventMapInformation(EVENT_RECORD *pEvent, string pMapName, byte *pBuffer, out uint pBufferSize);
internal static extern unsafe int GetEventInformation(EVENT_RECORD *pEvent, uint TdhContextCount, IntPtr pTdhContext, byte *pBuffer, out uint pBufferSize);
public EventRecordCPtr(EVENT_RECORD *pEventRecord) { this.pEventRecord = pEventRecord; }
public FastEventRecordCPtr(IntPtr pEventRecord) { this.pEventRecord = (EVENT_RECORD *)pEventRecord; }
private unsafe void Deserialize(EVENT_RECORD *eventRecord) { var providerId = eventRecord->ProviderId; var userData = eventRecord->UserData; // 8-byte aligned int pointerSize = (eventRecord->Flags & Etw.EVENT_HEADER_FLAG_64_BIT_HEADER) != 0 ? 8 : 4; if (this.sessionStartTimeQPC == 0) { this.sessionStartTimeQPC = eventRecord->TimeStamp; } /* https://msdn.microsoft.com/en-us/library/windows/desktop/dd392323(v=vs.85).aspx * [EventType{32}, EventTypeName{"Stack"}] * class StackWalk_Event : StackWalk * { * uint64 EventTimeStamp; * uint32 StackProcess; * uint32 StackThread; * uint32 Stack1; * uint32 Stack192; * }; */ if (eventRecord->ProviderId == KernelStackWalkEvent && eventRecord->Opcode == 32) { long eventTimestamp = ReadAlignedInt64(ref userData); uint pid = ReadAlignedUInt32(ref userData); uint tid = ReadAlignedUInt32(ref userData); int frameCount = (eventRecord->UserDataLength - sizeof(long) - sizeof(uint) - sizeof(uint)) / pointerSize; this.HandleStacks(userData, frameCount, eventTimestamp, pointerSize, pid, tid); return; } if (eventRecord->ExtendedDataCount > 0) { this.HandleExtendedData(eventRecord); } if ((providerId == ClrProviderGuid && eventRecord->Id == LoadVerbose) || (providerId == ClrRundownProviderGuid && (eventRecord->Id == DCStartVerbose || eventRecord->Id == DCStopVerbose))) { this.HandleMethodLoadEvent(eventRecord, userData); return; } if ((providerId == ClrProviderGuid && eventRecord->Id == ILToNativeMap) || (providerId == ClrRundownProviderGuid && (eventRecord->Id == ILToNativeMapDCStart || eventRecord->Id == ILToNativeMapDCStop))) { this.HandleILToNativeMappingEvent(userData); return; } if (providerId == ProcessLoadEvent) { this.HandleProcessEvents(eventRecord, userData, pointerSize); return; } if (providerId == ImageLoadEvent) { this.HandleImageLoadEvent(eventRecord, userData, pointerSize); return; } if (providerId == DbgIdEvent) { this.HandleDbgIdEvent(eventRecord, userData, pointerSize); return; } if ((providerId == ClrProviderGuid && eventRecord->Id == ModuleLoad) || (providerId == ClrRundownProviderGuid && (eventRecord->Id == ModuleDCStart || eventRecord->Id == ModuleDCStop))) { this.HandleModuleLoadEvent(eventRecord, userData); return; } }
internal unsafe RuntimeEventMetadata(EVENT_RECORD *eventRecord) { this.eventRecord = eventRecord; }
private static unsafe IEventTraceOperand BuildUnknownOperand(EVENT_RECORD *eventRecord, int metadataTableIndex) { return(new UnknownOperandBuilder(eventRecord->ProviderId, 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); }
internal unsafe EventRecordReader(EVENT_RECORD* eventRecord) { this.eventRecord = eventRecord; }