Exemple #1
0
        private unsafe void ProcessEventRecord(TraceEventNativeMethods.EVENT_RECORD *eventRecord, bool dispatch)
        {
            // BPerf writes a symbol db outside of the main file
            if (eventRecord->EventHeader.Id == BPerfManagedSymbolDatabaseLocationEventId && eventRecord->EventHeader.ProviderId == BPerfGuid)
            {
                this.ParseBPerfManagedSymbol(eventRecord);
            }

            // BPerf puts 65535 for Classic Events, TraceEvent fires an assert for that case.
            if ((eventRecord->EventHeader.Flags & TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0)
            {
                eventRecord->EventHeader.Id = 0;
            }

            var traceEvent = this.Lookup(eventRecord);

            traceEvent.DebugValidate();

            if (traceEvent.NeedsFixup)
            {
                traceEvent.FixupData();
            }

            if (dispatch)
            {
                this.Dispatch(traceEvent);
                this.sessionEndTimeQPC = Math.Max(eventRecord->EventHeader.TimeStamp, this.sessionEndTimeQPC);
            }
        }
        internal override unsafe Guid GetRelatedActivityID(TraceEventNativeMethods.EVENT_RECORD *eventRecord)
        {
            // Recover the EventPipeEventHeader from the payload pointer and then fetch from the header.
            EventPipeEventHeader *event_ = EventPipeEventHeader.HeaderFromPayloadPointer((byte *)eventRecord->UserData);

            return(event_->RelatedActivityID);
        }
        private void RawDispatch(TraceEventNativeMethods.EVENT_RECORD *rawData)
        {
            if (stopProcessing)
            {
                return;
            }

            if (lockObj != null)
            {
                Monitor.Enter(lockObj);
            }
            Debug.Assert(rawData->EventHeader.HeaderType == 0);     // if non-zero probably old-style ETW header
            TraceEvent anEvent = Lookup(rawData);

#if DEBUG
            anEvent.DisallowEventIndexAccess = DisallowEventIndexAccess;
#endif
            // Keep in mind that for UnhandledTraceEvent 'PrepForCallback' has NOT been called, which means the
            // opcode, guid and eventIds are not correct at this point.  The ToString() routine WILL call
            // this so if that is in your debug window, it will have this side effect (which is good and bad)
            // Looking at rawData will give you the truth however.
            anEvent.DebugValidate();

            if (anEvent.NeedsFixup)
            {
                anEvent.FixupData();
            }

            Dispatch(anEvent);

            if (lockObj != null)
            {
                Monitor.Exit(lockObj);
            }
        }
        public override bool Process()
        {
            if (_fileFormatVersionNumber >= 3)
            {
                // loop through the stream until we hit a null object.  Deserialization of
                // EventPipeEventBlocks will cause dispatch to happen.
                // ReadObject uses registered factories and recognizes types by names, then derserializes them with FromStream
                while (_deserializer.ReadObject() != null)
                {
                }
            }
#if SUPPORT_V1_V2
            else
            {
                PinnedStreamReader deserializerReader = (PinnedStreamReader)_deserializer.Reader;
                while (deserializerReader.Current < _endOfEventStream)
                {
                    TraceEventNativeMethods.EVENT_RECORD *eventRecord = ReadEvent(deserializerReader);
                    if (eventRecord != null)
                    {
                        // in the code below we set sessionEndTimeQPC to be the timestamp of the last event.
                        // Thus the new timestamp should be later, and not more than 1 day later.
                        Debug.Assert(sessionEndTimeQPC <= eventRecord->EventHeader.TimeStamp);
                        Debug.Assert(sessionEndTimeQPC == 0 || eventRecord->EventHeader.TimeStamp - sessionEndTimeQPC < _QPCFreq * 24 * 3600);

                        var traceEvent = Lookup(eventRecord);
                        Dispatch(traceEvent);
                        sessionEndTimeQPC = eventRecord->EventHeader.TimeStamp;
                    }
                }
            }
#endif
            return(true);
        }
Exemple #5
0
 /// <summary>
 /// Checks to see if eventRecord has TraceLogging meta data associated with it (EVENT_HEADER_EXT_TYPE_EVENT_SCHEMA_TL)
 /// and if so updates EventHeader.Id to be an event ID unique to that provider/opcode/meta-data blob.
 /// </summary>
 public void TestForTraceLoggingEventAndFixupIfNeeded(TraceEventNativeMethods.EVENT_RECORD *eventRecord)
 {
     // This method is designed to be inlined and thus have very low overhead for the non-tracelogging case.
     if (eventRecord->ExtendedDataCount != 0)
     {
         TestForTraceLoggingEventAndFixupIfNeededHelper(eventRecord);
     }
 }
Exemple #6
0
            private unsafe void Initialize(TraceEventNativeMethods.EVENT_RECORD *rawData)
            {
                var eventHeader = new EventTraceHeaderTraceData(null, 0xFFFF, 0, "EventTrace", KernelTraceEventParser.EventTraceTaskGuid, 0, "Header", KernelTraceEventParser.ProviderGuid, KernelTraceEventParser.ProviderName, null);

                eventHeader.source      = m_source;
                eventHeader.eventRecord = rawData;
                eventHeader.userData    = rawData->UserData;

                if (eventHeader.eventRecord->EventHeader.ProviderId != eventHeader.taskGuid || eventHeader.eventRecord->EventHeader.Opcode != 0)
                {
                    if (m_source._syncTimeQPC == 0)
                    {
                        // We did not get a if (m_source.sessionStartTimeQPC != 0) EventTraceHeaderTraceData either in the OnBeginProcessTrace callback (file based case) or the
                        // first event (real time case).   This is really a problem, as we need that information, but we will go ahead and
                        // try to initialize as best we can.

                        m_source.pointerSize        = sizeof(IntPtr);
                        m_source.numberOfProcessors = Environment.ProcessorCount;
                        m_source._QPCFreq           = Stopwatch.Frequency;
                        m_source._syncTimeUTC       = DateTime.UtcNow;
                        m_source._syncTimeQPC       = rawData->EventHeader.TimeStamp;

                        m_source.sessionStartTimeQPC = rawData->EventHeader.TimeStamp;
                        m_source.sessionEndTimeQPC   = long.MaxValue;
                    }
                    return;
                }

                m_source.m_eventsLost += eventHeader.EventsLost;
                if (m_source._syncTimeQPC != 0)
                {
                    return;
                }

                m_source.pointerSize = eventHeader.PointerSize;
                Debug.Assert(m_source.pointerSize == 4 || m_source.pointerSize == 8);
                m_source.numberOfProcessors = eventHeader.NumberOfProcessors;
                Debug.Assert(m_source.numberOfProcessors < 10000);
                m_source.cpuSpeedMHz      = eventHeader.CPUSpeed;
                m_source.utcOffsetMinutes = eventHeader.UTCOffsetMinutes;
                int ver = eventHeader.Version;

                m_source.osVersion           = new Version((byte)ver, (byte)(ver >> 8));
                m_source._QPCFreq            = eventHeader.PerfFreq;
                m_source._syncTimeUTC        = DateTime.FromFileTimeUtc(eventHeader.StartTime100ns);
                m_source._syncTimeQPC        = rawData->EventHeader.TimeStamp;
                m_source.sessionStartTimeQPC = rawData->EventHeader.TimeStamp;

                if (eventHeader.EndTime100ns == 0)
                {
                    m_source.sessionEndTimeQPC = long.MaxValue;
                }
                else
                {
                    m_source.sessionEndTimeQPC = m_source.UTCDateTimeToQPC(DateTime.FromFileTimeUtc(eventHeader.EndTime100ns));
                }
            }
        internal TraceEventNativeMethods.EVENT_RECORD *ReadEvent(PinnedStreamReader reader)
        {
            EventPipeEventHeader *eventData = (EventPipeEventHeader *)reader.GetPointer(EventPipeEventHeader.HeaderSize);

            eventData = (EventPipeEventHeader *)reader.GetPointer(eventData->TotalEventSize); // now we now the real size and get read entire event

            // Basic sanity checks.  Are the timestamps and sizes sane.
            Debug.Assert(sessionEndTimeQPC <= eventData->TimeStamp);
            Debug.Assert(sessionEndTimeQPC == 0 || eventData->TimeStamp - sessionEndTimeQPC < _QPCFreq * 24 * 3600);
            Debug.Assert(0 <= eventData->PayloadSize && eventData->PayloadSize <= eventData->TotalEventSize);
            Debug.Assert(0 < eventData->TotalEventSize && eventData->TotalEventSize < 0x20000);                               // TODO really should be 64K but BulkSurvivingObjectRanges needs fixing.
            Debug.Assert(_fileFormatVersionNumber < 3 ||
                         ((int)EventPipeEventHeader.PayloadBytes(eventData) % 4 == 0 && eventData->TotalEventSize % 4 == 0)); // ensure 4 byte alignment

            StreamLabel eventDataEnd = reader.Current.Add(eventData->TotalEventSize);

            Debug.Assert(0 <= EventPipeEventHeader.StackBytesSize(eventData) && EventPipeEventHeader.StackBytesSize(eventData) <= eventData->TotalEventSize);

            TraceEventNativeMethods.EVENT_RECORD *ret = null;
            if (eventData->IsMetadata())
            {
                int totalEventSize = eventData->TotalEventSize;
                int payloadSize    = eventData->PayloadSize;

                // Note that this skip invalidates the eventData pointer, so it is important to pull any fields out we need first.
                reader.Skip(EventPipeEventHeader.HeaderSize);

                StreamLabel metaDataEnd = reader.Current.Add(payloadSize);

                // Read in the header (The header does not include payload parameter information)
                var metaDataHeader = new EventPipeEventMetaDataHeader(reader, payloadSize, _fileFormatVersionNumber, PointerSize, _processId);
                _eventMetadataDictionary.Add(metaDataHeader.MetaDataId, metaDataHeader);

                // Tell the parser about this new event
                _eventParser.OnNewEventPipeEventDefinition(metaDataHeader, reader);
                Debug.Assert(reader.Current == metaDataEnd);    // We should have read all the meta-data.

                int stackBytes = reader.ReadInt32();
                Debug.Assert(stackBytes == 0, "Meta-data events should always have a empty stack");
            }
            else
            {
                if (_eventMetadataDictionary.TryGetValue(eventData->MetaDataId, out var metaData))
                {
                    ret = metaData.GetEventRecordForEventData(eventData);
                }
                else
                {
                    Debug.Assert(false, "Warning can't find metaData for ID " + eventData->MetaDataId.ToString("x"));
                }
            }

            reader.Goto(eventDataEnd);

            return(ret);
        }
Exemple #8
0
        private unsafe bool Initialize(TraceEventNativeMethods.EVENT_RECORD *eventRecord)
        {
            if (eventRecord->EventHeader.ProviderId == EventTraceGuid)
            {
                var logfile = (FAKE_TRACE_LOGFILE_HEADER *)eventRecord->UserData;
                this.pointerSize         = (int)logfile->PointerSize;
                this._QPCFreq            = logfile->PerfFreq;
                this.osVersion           = new Version((byte)logfile->Version, (byte)(logfile->Version >> 8));
                this.cpuSpeedMHz         = (int)logfile->CpuSpeedInMHz;
                this.numberOfProcessors  = (int)logfile->NumberOfProcessors;
                this.utcOffsetMinutes    = logfile->Bias;
                this._syncTimeUTC        = DateTime.FromFileTimeUtc(logfile->StartTime);
                this._syncTimeQPC        = eventRecord->EventHeader.TimeStamp;
                this.sessionStartTimeQPC = eventRecord->EventHeader.TimeStamp;
                this.sessionEndTimeQPC   = eventRecord->EventHeader.TimeStamp;
                this.eventsLost          = (int)logfile->EventsLost;

                var kernelParser = new KernelTraceEventParser(this, KernelTraceEventParser.ParserTrackingOptions.None);

                kernelParser.EventTraceHeader += delegate(EventTraceHeaderTraceData data)
                {
                    Marshal.WriteInt32(data.userData, OffsetToUTCOffsetMinutes, this.utcOffsetMinutes.Value); // Since this is a FakeTraceHeader
                };

                kernelParser.ProcessStartGroup += delegate(ProcessTraceData data)
                {
                    string path     = data.KernelImageFileName;
                    int    startIdx = path.LastIndexOf('\\');
                    if (0 <= startIdx)
                    {
                        startIdx++;
                    }
                    else
                    {
                        startIdx = 0;
                    }

                    int endIdx = path.LastIndexOf('.');
                    if (endIdx <= startIdx)
                    {
                        endIdx = path.Length;
                    }

                    this.processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
                };

                kernelParser.ProcessEndGroup += delegate(ProcessTraceData data)
                {
                    this.processNameForID.Remove(data.ProcessID);
                };

                return(true);
            }

            return(false);
        }
        private TraceEventNativeMethods.EVENT_RECORD *ReadEvent(PinnedStreamReader reader)
        {
            // Guess that the event is < 1000 bytes or whatever is left in the stream.
            int eventSizeGuess = Math.Min(1000, _endOfEventStream.Sub(reader.Current));
            EventPipeEventHeader *eventData = (EventPipeEventHeader *)reader.GetPointer(eventSizeGuess);

            // Basic sanity checks.  Are the timestamps and sizes sane.
            Debug.Assert(sessionEndTimeQPC <= eventData->TimeStamp);
            Debug.Assert(sessionEndTimeQPC == 0 || eventData->TimeStamp - sessionEndTimeQPC < _QPCFreq * 24 * 3600);
            Debug.Assert(0 <= eventData->PayloadSize && eventData->PayloadSize <= eventData->TotalEventSize);
            Debug.Assert(eventData->MetaDataId <= reader.Current);                              // IDs are the location in the of of the data, so it comes before
            Debug.Assert(0 < eventData->TotalEventSize && eventData->TotalEventSize < 0x20000); // TODO really should be 64K but BulkSurvivingObjectRanges needs fixing.

            if (eventSizeGuess < eventData->TotalEventSize)
            {
                eventData = (EventPipeEventHeader *)reader.GetPointer(eventData->TotalEventSize);
            }

            Debug.Assert(0 <= EventPipeEventHeader.StackBytesSize(eventData) && EventPipeEventHeader.StackBytesSize(eventData) <= eventData->TotalEventSize);
            // This asserts that the header size + payload + stackSize field + StackSize == TotalEventSize;
            Debug.Assert(eventData->PayloadSize + EventPipeEventHeader.HeaderSize + sizeof(int) + EventPipeEventHeader.StackBytesSize(eventData) == eventData->TotalEventSize);

            TraceEventNativeMethods.EVENT_RECORD *ret = null;
            EventPipeEventMetaData metaData;

            if (eventData->MetaDataId == 0)     // Is this a Meta-data event?
            {
                int         totalEventSize       = eventData->TotalEventSize;
                int         payloadSize          = eventData->PayloadSize;
                StreamLabel metaDataStreamOffset = reader.Current;  // Used as the 'id' for the meta-data
                // Note that this skip invalidates the eventData pointer, so it is important to pull any fields out we need first.
                reader.Skip(EventPipeEventHeader.HeaderSize);
                metaData = new EventPipeEventMetaData(reader, payloadSize, _fileFormatVersionNumber, PointerSize, _processId);
                _eventMetadataDictionary.Add(metaDataStreamOffset, metaData);
                _eventParser.AddTemplate(metaData);
                int stackBytes = reader.ReadInt32();        // Meta-data events should always have a empty stack.
                Debug.Assert(stackBytes == 0);

                // We have read all the bytes in the event
                Debug.Assert(reader.Current == metaDataStreamOffset.Add(totalEventSize));
            }
            else
            {
                if (_eventMetadataDictionary.TryGetValue(eventData->MetaDataId, out metaData))
                {
                    ret = metaData.GetEventRecordForEventData(eventData);
                }
                else
                {
                    Debug.Assert(false, "Warning can't find metaData for ID " + eventData->MetaDataId.ToString("x"));
                }
                reader.Skip(eventData->TotalEventSize);
            }

            return(ret);
        }
        internal TraceEventNativeMethods.EVENT_RECORD *ReadEvent(PinnedStreamReader reader)
        {
            EventPipeEventHeader *eventData = (EventPipeEventHeader *)reader.GetPointer(EventPipeEventHeader.HeaderSize);

            eventData = (EventPipeEventHeader *)reader.GetPointer(eventData->TotalEventSize); // now we now the real size and get read entire event

            // Basic sanity checks.  Are the timestamps and sizes sane.
            Debug.Assert(sessionEndTimeQPC <= eventData->TimeStamp);
            Debug.Assert(sessionEndTimeQPC == 0 || eventData->TimeStamp - sessionEndTimeQPC < _QPCFreq * 24 * 3600);
            Debug.Assert(0 <= eventData->PayloadSize && eventData->PayloadSize <= eventData->TotalEventSize);
            Debug.Assert(0 < eventData->TotalEventSize && eventData->TotalEventSize < 0x20000);                               // TODO really should be 64K but BulkSurvivingObjectRanges needs fixing.
            Debug.Assert(_fileFormatVersionNumber < 3 ||
                         ((int)EventPipeEventHeader.PayloadBytes(eventData) % 4 == 0 && eventData->TotalEventSize % 4 == 0)); // ensure 4 byte alignment

            StreamLabel eventDataEnd = reader.Current.Add(eventData->TotalEventSize);

            Debug.Assert(0 <= EventPipeEventHeader.StackBytesSize(eventData) && EventPipeEventHeader.StackBytesSize(eventData) <= eventData->TotalEventSize);

            TraceEventNativeMethods.EVENT_RECORD *ret = null;;
            if (eventData->IsMetadata())
            {
                int totalEventSize = eventData->TotalEventSize;
                int payloadSize    = eventData->PayloadSize;

                // Note that this skip invalidates the eventData pointer, so it is important to pull any fields out we need first.
                reader.Skip(EventPipeEventHeader.HeaderSize);

                var metaData = new EventPipeEventMetaData(reader, payloadSize, _fileFormatVersionNumber, PointerSize, _processId);
                _eventMetadataDictionary.Add(metaData.MetaDataId, metaData);

                _eventParser.AddTemplate(metaData); // if we don't add the templates to this parse, we are going to have unhadled events (see https://github.com/Microsoft/perfview/issues/461)

                int stackBytes = reader.ReadInt32();
                Debug.Assert(stackBytes == 0, "Meta-data events should always have a empty stack");
            }
            else
            {
                if (_eventMetadataDictionary.TryGetValue(eventData->MetaDataId, out var metaData))
                {
                    ret = metaData.GetEventRecordForEventData(eventData);
                }
                else
                {
                    Debug.Assert(false, "Warning can't find metaData for ID " + eventData->MetaDataId.ToString("x"));
                }
            }

            reader.Goto(eventDataEnd);

            return(ret);
        }
Exemple #11
0
        /// <summary>
        /// Checks to see if this event has TraceLogging meta data associated with it (EVENT_HEADER_EXT_TYPE_EVENT_SCHEMA_TL)
        /// and if so updates EventHeader.Id to be an event ID unique to that provider/opcode/meta-data blob.
        /// </summary>
        private void TestForTraceLoggingEventAndFixupIfNeededHelper(TraceEventNativeMethods.EVENT_RECORD *eventRecord)
        {
            var ptr = eventRecord->ExtendedData;
            var end = &eventRecord->ExtendedData[eventRecord->ExtendedDataCount];

            while (ptr < end)
            {
                if (ptr->ExtType == TraceEventNativeMethods.EVENT_HEADER_EXT_TYPE_EVENT_SCHEMA_TL)
                {
                    eventRecord->EventHeader.Id = GetEventIDForTraceLoggingEvent(eventRecord, ptr);
                }
                ptr++;
            }
        }
Exemple #12
0
        unsafe void SendEvent(Guid providerGuid, int eventID, bool isClassic = false)
        {
            TraceEventNativeMethods.EVENT_RECORD  rawDataStorage;
            TraceEventNativeMethods.EVENT_RECORD *rawData = &rawDataStorage;
            rawData->EventHeader.ProviderId = providerGuid;
            rawData->EventHeader.Id         = (ushort)eventID;
            rawData->EventHeader.Flags      = 0;
            if (isClassic)
            {
                rawData->EventHeader.Flags = TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER;
            }

            var event_ = m_dispatcher.Lookup(rawData);

            m_dispatcher.Dispatch(event_);
        }
Exemple #13
0
        private void RawDispatchClassic(TraceEventNativeMethods.EVENT_RECORD *eventData)
        {
            // TODO not really a EVENT_RECORD on input, but it is a pain to be type-correct.
            TraceEventNativeMethods.EVENT_TRACE *oldStyleHeader = (TraceEventNativeMethods.EVENT_TRACE *)eventData;
            eventData = convertedHeader;

            eventData->EventHeader.Size = (ushort)sizeof(TraceEventNativeMethods.EVENT_TRACE_HEADER);
            // HeaderType
            eventData->EventHeader.Flags = TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER;

            // TODO Figure out if there is a marker that is used in the WOW for the classic providers
            // right now I assume they are all the same as the machine.
            if (pointerSize == 8)
            {
                eventData->EventHeader.Flags |= TraceEventNativeMethods.EVENT_HEADER_FLAG_64_BIT_HEADER;
            }
            else
            {
                eventData->EventHeader.Flags |= TraceEventNativeMethods.EVENT_HEADER_FLAG_32_BIT_HEADER;
            }

            // EventProperty
            eventData->EventHeader.ThreadId   = oldStyleHeader->Header.ThreadId;
            eventData->EventHeader.ProcessId  = oldStyleHeader->Header.ProcessId;
            eventData->EventHeader.TimeStamp  = oldStyleHeader->Header.TimeStamp;
            eventData->EventHeader.ProviderId = oldStyleHeader->Header.Guid;            // ProviderId = TaskId
            // ID left 0
            eventData->EventHeader.Version = (byte)oldStyleHeader->Header.Version;
            // Channel
            eventData->EventHeader.Level  = oldStyleHeader->Header.Level;
            eventData->EventHeader.Opcode = oldStyleHeader->Header.Type;
            // Task
            // Keyword
            eventData->EventHeader.KernelTime = oldStyleHeader->Header.KernelTime;
            eventData->EventHeader.UserTime   = oldStyleHeader->Header.UserTime;
            // ActivityID

            eventData->BufferContext = oldStyleHeader->BufferContext;
            // ExtendedDataCount
            eventData->UserDataLength = (ushort)oldStyleHeader->MofLength;
            // ExtendedData
            eventData->UserData = oldStyleHeader->MofData;
            // UserContext

            RawDispatch(eventData);
        }
Exemple #14
0
        private void RawDispatch(TraceEventNativeMethods.EVENT_RECORD *rawData)
        {
            Debug.Assert(rawData->EventHeader.HeaderType == 0);     // if non-zero probably old-style ETW header
            TraceEvent anEvent = Lookup(rawData);

            // Keep in mind that for UnhandledTraceEvent 'PrepForCallback' has NOT been called, which means the
            // opcode, guid and eventIds are not correct at this point.  The ToString() routine WILL call
            // this so if that is in your debug window, it will have this side effect (which is good and bad)
            // Looking at rawData will give you the truth however.
            anEvent.DebugValidate();

            if (anEvent.FixupETLData != null)
            {
                anEvent.FixupETLData();
            }
            Dispatch(anEvent);
        }
Exemple #15
0
        /// <summary>
        /// given that 'eventRecord' is a TraceLogging event (with meta-data 'metaData'), return a eventID that is unique
        /// to that provider/opcode/meta-data blob.
        /// </summary>
        private ushort GetEventIDForTraceLoggingEvent(TraceEventNativeMethods.EVENT_RECORD *eventRecord, TraceEventNativeMethods.EVENT_HEADER_EXTENDED_DATA_ITEM *metaData)
        {
            Debug.Assert(metaData->ExtType == TraceEventNativeMethods.EVENT_HEADER_EXT_TYPE_EVENT_SCHEMA_TL);
            if (m_traceLoggingEventMap == null)     // Lazy init.
            {
                m_traceLoggingEventMap          = new Dictionary <ProviderMetaDataKey, ushort>();
                m_nextTraceLoggingIDForProvider = new Dictionary <Guid, ushort>();
            }

            // Check if I am in the table of assigned eventIds for this meta-data- blob
            ProviderMetaDataKey key = new ProviderMetaDataKey(&eventRecord->EventHeader.ProviderId, eventRecord->EventHeader.Opcode, (byte *)metaData->DataPtr, metaData->DataSize);
            ushort ret;

            if (!m_traceLoggingEventMap.TryGetValue(key, out ret))
            {
                // No then get the next ID for this particular provider (and allocate a new one)
                if (!m_nextTraceLoggingIDForProvider.TryGetValue(eventRecord->EventHeader.ProviderId, out ret))
                {
                    ret = 0xFF00;   // We arbitrarily pick the 'high end' of the event ID range to stay way from user-allocated IDs.   However we also avoid the last 256 ID just in case.
                }

                --ret;
                m_nextTraceLoggingIDForProvider[eventRecord->EventHeader.ProviderId] = ret;
                if (ret == 0) // means we wrapped around.  We have no more!
                {
                    throw new InvalidOperationException("Error ran out of TraceLogging Event IDs for provider " + eventRecord->EventHeader.ProviderId);
                }

                // Make a copy of memory the key points at.   Thus the table 'owns' the data the keys point at.
                // This is reclaimed in 'Dispose'
                int   copyDataSize = (key.DataSize + 3) & ~3;       // round it up to a multiple of 4.  CopyBlob requires this.
                byte *copy         = (byte *)Marshal.AllocHGlobal(copyDataSize + sizeof(Guid));
                key.Provider = (Guid *)(copy);
                *key.Provider = eventRecord->EventHeader.ProviderId;
                copy += sizeof(Guid);
                TraceEvent.CopyBlob((IntPtr)key.Data, (IntPtr)copy, copyDataSize);
                key.Data = copy;

                // Add the new key and eventID to the table.
                m_traceLoggingEventMap.Add(key, ret);
            }
            return(ret);
        }
Exemple #16
0
        private unsafe void ProcessEventRecord(TraceEventNativeMethods.EVENT_RECORD *eventRecord, bool dispatch)
        {
            // BPerf writes a symbol db outside of the main file
            if (eventRecord->EventHeader.Id == BPerfManagedSymbolDatabaseLocationEventId && eventRecord->EventHeader.ProviderId == BPerfGuid)
            {
                this.ParseBPerfManagedSymbol(eventRecord);
            }

            // BPerf puts 65535 for Classic Events, TraceEvent fires an assert for that case.
            if ((eventRecord->EventHeader.Flags & TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0)
            {
                eventRecord->EventHeader.Id = 0;
            }

            var traceEvent = this.Lookup(eventRecord);

            traceEvent.DebugValidate();

            if (traceEvent.NeedsFixup)
            {
                traceEvent.FixupData();
            }

            if (dispatch)
            {
                bool eventNeededForSymbolResolution = false;
                if (this.canResolveSymbols)
                {
                    ref Guid providerId = ref eventRecord->EventHeader.ProviderId;
                    eventNeededForSymbolResolution = providerId == ClrGuid
                        ? eventRecord->EventHeader.Id == 190 ||
                                                     eventRecord->EventHeader.Id >= 143 && eventRecord->EventHeader.Id <= 157
                        : providerId == ImageLoadGuid || providerId == ProcessGuid || providerId == VolumeMappingGuid || providerId == KernelTraceControlImageIdGuid || providerId == KernelTraceControlMetaDataGuid;
                }

                if (eventRecord->EventHeader.TimeStamp >= this.skipQPC || eventNeededForSymbolResolution)
                {
                    this.Dispatch(traceEvent);
                    this.sessionEndTimeQPC = Math.Max(eventRecord->EventHeader.TimeStamp, this.sessionEndTimeQPC);
                }
            }
        public override bool Process()
        {
            PinnedStreamReader deserializerReader = (PinnedStreamReader)_deserializer.Reader;

            deserializerReader.Goto(_startEventOfStream);
            while (deserializerReader.Current < _endOfEventStream)
            {
                TraceEventNativeMethods.EVENT_RECORD *eventRecord = ReadEvent(deserializerReader);
                if (eventRecord != null)
                {
                    // in the code below we set sessionEndTimeQPC to be the timestamp of the last event.
                    // Thus the new timestamp should be later, and not more than 1 day later.
                    Debug.Assert(sessionEndTimeQPC <= eventRecord->EventHeader.TimeStamp);
                    Debug.Assert(sessionEndTimeQPC == 0 || eventRecord->EventHeader.TimeStamp - sessionEndTimeQPC < _QPCFreq * 24 * 3600);

                    TraceEvent event_ = Lookup(eventRecord);
                    Dispatch(event_);
                    sessionEndTimeQPC = eventRecord->EventHeader.TimeStamp;
                }
            }

            return(true);
        }
Exemple #18
0
        private unsafe void ParseBPerfManagedSymbol(TraceEventNativeMethods.EVENT_RECORD *eventRecord)
        {
            var bperfLogLocation = Path.Combine(Path.GetDirectoryName(this.btlFilePath), Path.GetFileName(Marshal.PtrToStringAnsi(eventRecord->UserData)));

            if (!File.Exists(bperfLogLocation))
            {
                return;
            }

            var firstDot  = bperfLogLocation.IndexOf('.') + 1;
            var nextDot   = bperfLogLocation.IndexOf('.', firstDot);
            var processId = int.Parse(bperfLogLocation.Substring(firstDot, nextDot - firstDot));

            long length;

            using (var fs = new FileStream(bperfLogLocation, FileMode.Open, FileAccess.ReadWrite))
            {
                length = fs.Length;
            }

            using (var mmapedFile = MemoryMappedFile.CreateFromFile(bperfLogLocation))
            {
                var   accessor = mmapedFile.CreateViewAccessor(0, length, MemoryMappedFileAccess.Read);
                byte *ptr      = (byte *)0;
                accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);

                const int HeaderSize = 16;

                long position = 0;
                while (position + HeaderSize < length)
                {
                    var eventIdToken   = accessor.ReadByte(position);
                    var version        = accessor.ReadByte(position + 1);
                    var flags          = accessor.ReadUInt16(position + 2);
                    var eventId        = accessor.ReadUInt16(position + 4);
                    var userDataLength = accessor.ReadUInt16(position + 6);
                    var timestamp      = accessor.ReadInt64(position + 8);

                    position += HeaderSize;

                    if (position + userDataLength <= length)
                    {
                        if (timestamp <= this.endQPC)
                        {
                            TraceEventNativeMethods.EVENT_RECORD e;
                            e.ExtendedDataCount     = 0;
                            e.UserDataLength        = userDataLength;
                            e.UserData              = new IntPtr(ptr + position);
                            e.EventHeader.TimeStamp = timestamp < this.sessionEndTimeQPC ? this.sessionEndTimeQPC : timestamp;
                            e.EventHeader.Flags     = flags;
                            e.EventHeader.ThreadId  = 0;
                            e.EventHeader.ProcessId = processId;
                            e.EventHeader.Version   = version;
                            e.EventHeader.Id        = eventId;

                            if (eventIdToken == 0)
                            {
                                e.EventHeader.Version    = 0;
                                e.EventHeader.Opcode     = 35;
                                e.EventHeader.Flags      = TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER | TraceEventNativeMethods.EVENT_HEADER_FLAG_64_BIT_HEADER;
                                e.EventHeader.ProviderId = VolumeMappingGuid;

                                this.ProcessEventRecord(&e, dispatch: true);
                            }
                            else if (eventIdToken == 1 && eventId == 5)
                            {
                                e.EventHeader.Version    = 3;
                                e.EventHeader.Opcode     = 10;
                                e.EventHeader.Flags      = TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER | TraceEventNativeMethods.EVENT_HEADER_FLAG_64_BIT_HEADER;
                                e.EventHeader.ProviderId = ImageLoadGuid;

                                // BEGIN HACK Alert: We transform a manifest event into classic because of limitations pre-Win8

                                e.UserDataLength = (ushort)(userDataLength - 36 + 56);
                                var tmp = new byte[e.UserDataLength];
                                Marshal.Copy(e.UserData, tmp, 0, 36);
                                Marshal.Copy(e.UserData + 36, tmp, 56, userDataLength - 36);

                                fixed(byte *t = &tmp[0])
                                {
                                    e.UserData = new IntPtr(t);
                                    this.ProcessEventRecord(&e, dispatch: true);
                                }

                                // END HACK Alert: We transform a manifest event into classic because of limitations pre-Win8
                            }
                            else if (eventIdToken == 2)
                            {
                                e.EventHeader.ProviderId = ClrGuid;

                                this.ProcessEventRecord(&e, dispatch: true);
                            }
                        }
                    }

                    position += userDataLength;
                }
            }
        }
 internal static extern int TdhGetEventInformation(
     TraceEventNativeMethods.EVENT_RECORD *pEvent,
     uint TdhContextCount,
     void *pTdhContext,
     byte *pBuffer,
     int *pBufferSize);
 internal static extern int TdhGetEventMapInformation(
     TraceEventNativeMethods.EVENT_RECORD *pEvent,
     string pMapName,
     EVENT_MAP_INFO *info,
     ref int infoSize
     );
Exemple #21
0
        private unsafe void ParseBPerfManagedSymbol(TraceEventNativeMethods.EVENT_RECORD *eventRecord)
        {
            var bperfLogLocation = Path.Combine(Path.GetDirectoryName(this.btlFilePath), Path.GetFileName(Marshal.PtrToStringUni(eventRecord->UserData)));

            if (!File.Exists(bperfLogLocation))
            {
                return;
            }

            var firstDot  = bperfLogLocation.IndexOf('.') + 1;
            var nextDot   = bperfLogLocation.IndexOf('.', firstDot);
            var processId = int.Parse(bperfLogLocation.Substring(firstDot, nextDot - firstDot));

            using (var fs = new FileStream(bperfLogLocation, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                long length = fs.Length;

#if NET462
                using (var mmapedFile = MemoryMappedFile.CreateFromFile(fs, null, length, MemoryMappedFileAccess.Read, null, HandleInheritability.None, true))
#else
                using (var mmapedFile = MemoryMappedFile.CreateFromFile(fs, null, length, MemoryMappedFileAccess.Read, HandleInheritability.None, true))
#endif
                {
                    var   accessor = mmapedFile.CreateViewAccessor(0, length, MemoryMappedFileAccess.Read);
                    byte *ptr      = (byte *)0;
                    accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);

                    const int HeaderSize = 16;

                    long position = 0;
                    while (position + HeaderSize < length)
                    {
                        var eventIdToken   = accessor.ReadByte(position);
                        var version        = accessor.ReadByte(position + 1);
                        var flags          = accessor.ReadUInt16(position + 2);
                        var eventId        = accessor.ReadUInt16(position + 4);
                        var userDataLength = accessor.ReadUInt16(position + 6);
                        var timestamp      = accessor.ReadInt64(position + 8);

                        position += HeaderSize;

                        if (position + userDataLength <= length)
                        {
                            if (timestamp <= this.endQPCForManagedSymbolsInclusion)
                            {
                                if (eventIdToken == 2) // CLR Events
                                {
                                    TraceEventNativeMethods.EVENT_RECORD e;
                                    e.ExtendedDataCount      = 0;
                                    e.UserDataLength         = userDataLength;
                                    e.UserData               = new IntPtr(ptr + position);
                                    e.EventHeader.TimeStamp  = timestamp < this.sessionEndTimeQPC ? this.sessionEndTimeQPC : timestamp;
                                    e.EventHeader.Flags      = flags;
                                    e.EventHeader.ThreadId   = 0;
                                    e.EventHeader.ProcessId  = processId;
                                    e.EventHeader.Version    = version;
                                    e.EventHeader.Id         = eventId;
                                    e.EventHeader.ProviderId = ClrGuid;

                                    this.ProcessEventRecord(&e, dispatch: true);
                                }
                            }
                        }

                        position += userDataLength;
                    }
                }
            }
        }
        public ETWTraceEventSource(string fileOrSessionName, TraceEventSourceType type)
        {
            long now = DateTime.Now.ToFileTime() - 100000;     // subtract 10ms to avoid negative times.

            primaryLogFile = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW();
            primaryLogFile.BufferCallback = this.TraceEventBufferCallback;

            useClassicETW = Environment.OSVersion.Version.Major < 6;
            if (useClassicETW)
            {
                IntPtr mem = TraceEventNativeMethods.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD));
                TraceEventNativeMethods.ZeroMemory(mem, (uint)sizeof(TraceEventNativeMethods.EVENT_RECORD));
                convertedHeader = (TraceEventNativeMethods.EVENT_RECORD*)mem;
                primaryLogFile.EventCallback = RawDispatchClassic;

            }
            else
            {
                primaryLogFile.LogFileMode = TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD;
                primaryLogFile.EventCallback = RawDispatch;
            }

            if (type == TraceEventSourceType.Session)
            {
                primaryLogFile.LoggerName = fileOrSessionName;
                primaryLogFile.LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
            }
            else
            {
                if (type == TraceEventSourceType.UserAndKernelFile)
                {
                    // See if we have also have kernel log moduleFile.
                    if (fileOrSessionName.Length > 4 && string.Compare(fileOrSessionName, fileOrSessionName.Length - 4, ".etl", 0, 4, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        string kernelFileName = fileOrSessionName.Substring(0, fileOrSessionName.Length - 4) + ".kernel.etl";
                        if (File.Exists(kernelFileName))
                        {
                            if (File.Exists(fileOrSessionName))
                            {
                                handles = new ulong[2];
                                handles[0] = TraceEventNativeMethods.INVALID_HANDLE_VALUE;

                                kernelModeLogFile = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW();
                                kernelModeLogFile.BufferCallback = primaryLogFile.BufferCallback;
                                kernelModeLogFile.EventCallback = primaryLogFile.EventCallback;
                                kernelModeLogFile.LogFileName = kernelFileName;
                                kernelModeLogFile.LogFileMode = primaryLogFile.LogFileMode;

                                handles[1] = TraceEventNativeMethods.OpenTrace(ref kernelModeLogFile);

                                if (TraceEventNativeMethods.INVALID_HANDLE_VALUE == handles[1])
                                    Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());

                            }
                            else
                            {
                                // we have ONLY a *.kernel.etl moduleFile, treat it as the primary moduleFile.
                                fileOrSessionName = kernelFileName;
                            }
                        }
                    }
                    if (!File.Exists(fileOrSessionName))
                        throw new FileNotFoundException("Unable to find the file " + fileOrSessionName);
                }
                primaryLogFile.LogFileName = fileOrSessionName;
            }

            // Open the main data source
            if (handles == null)
                handles = new ulong[1];

            handles[0] = TraceEventNativeMethods.OpenTrace(ref primaryLogFile);

            if (TraceEventNativeMethods.INVALID_HANDLE_VALUE == handles[0])
                Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());

            // Session offset time is the minimum of all times.
            sessionStartTime100ns = primaryLogFile.LogfileHeader.StartTime;
            if (handles.Length == 2 && kernelModeLogFile.LogfileHeader.StartTime < sessionStartTime100ns)
                sessionStartTime100ns = kernelModeLogFile.LogfileHeader.StartTime;

            // Real time providers don't set this to something useful
            if (sessionStartTime100ns == 0)
                sessionStartTime100ns = now;

            sessionEndTime100ns = primaryLogFile.LogfileHeader.EndTime;
            if (handles.Length == 2 && sessionEndTime100ns < kernelModeLogFile.LogfileHeader.EndTime)
                sessionEndTime100ns = kernelModeLogFile.LogfileHeader.EndTime;

            if (sessionEndTime100ns == 0)
                sessionEndTime100ns = sessionStartTime100ns;

            // TODO remove when we do per-event stuff.
            pointerSize = (int)primaryLogFile.LogfileHeader.PointerSize;
            if (handles.Length == 2)
                pointerSize = (int) kernelModeLogFile.LogfileHeader.PointerSize;

            if (pointerSize == 0)
            {
                pointerSize = sizeof(IntPtr);
                Debug.Assert((primaryLogFile.LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(pointerSize == 4 || pointerSize == 8);

            eventsLost = (int)primaryLogFile.LogfileHeader.EventsLost;
            cpuSpeedMHz = (int)primaryLogFile.LogfileHeader.CpuSpeedInMHz;
            numberOfProcessors = (int)primaryLogFile.LogfileHeader.NumberOfProcessors;

            // Logic for looking up process names
            processNameForID = new Dictionary<int, string>();
            Kernel.ProcessStartGroup += delegate(ProcessTraceData data) {
                // Get just the file name without the extension.  Can't use the 'Path' class because
                // it tests to make certain it does not have illegal chars etc.  Since KernelImageFileName
                // is not a true user mode path, we can get failures.
                string path = data.KernelImageFileName;
                int startIdx = path.LastIndexOf('\\');
                if (0 <= startIdx)
                    startIdx++;
                else
                    startIdx = 0;
                int endIdx = path.LastIndexOf('.', startIdx);
                if (endIdx < 0)
                    endIdx = path.Length;
                processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
            };
        }