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;
            }
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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)));
                }
            }
        }
Beispiel #11
0
        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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
            }
        }
Beispiel #14
0
        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;
            }
            }
        }
Beispiel #16
0
 internal unsafe EventRecordReader(EVENT_RECORD *eventRecord)
 {
     this.eventRecord = eventRecord;
 }
 internal unsafe RuntimeEventMetadata(EVENT_RECORD* eventRecord)
 {
     this.eventRecord = eventRecord;
 }
Beispiel #18
0
 internal static extern unsafe int GetEventMapInformation(EVENT_RECORD *pEvent, string pMapName, byte *pBuffer, out uint pBufferSize);
Beispiel #19
0
 internal static extern unsafe int GetEventInformation(EVENT_RECORD *pEvent, uint TdhContextCount, IntPtr pTdhContext, byte *pBuffer, out uint pBufferSize);
Beispiel #20
0
 public EventRecordCPtr(EVENT_RECORD *pEventRecord)
 {
     this.pEventRecord = pEventRecord;
 }
Beispiel #21
0
 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;
            }
        }
Beispiel #23
0
 internal unsafe RuntimeEventMetadata(EVENT_RECORD *eventRecord)
 {
     this.eventRecord = eventRecord;
 }
Beispiel #24
0
 private static unsafe IEventTraceOperand BuildUnknownOperand(EVENT_RECORD *eventRecord, int metadataTableIndex)
 {
     return(new UnknownOperandBuilder(eventRecord->ProviderId, metadataTableIndex));
 }
Beispiel #25
0
        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;
 }