private void ReadAndDispatchTraceEvent(StreamLabel eventStart, uint eventSize) { // Read the metadata label. StreamLabel metadataLabel = (StreamLabel)_deserializer.ReadInt(); // 0 is the label for metadata. if (metadataLabel == 0) { ReadAndUpdateEventMetadataDictionary(eventStart); } else { EventMetadata eventMetadata; if (_eventMetadataDictionary.TryGetValue(metadataLabel, out eventMetadata)) { ReadAndDispatchTraceEvent(eventMetadata); } else { Debug.Fail($"Unable to find metadata for {metadataLabel}."); // Skip the event _deserializer.Goto(eventStart + eventSize); } } }
void IFastSerializable.FromStream(Deserializer deserializer) { BeforeValue = deserializer.ReadInt(); StreamLabel label = deserializer.Reader.ReadLabel(); Assert.Equal((ulong)0x7EADBEEF, (ulong)label); AfterValue = deserializer.ReadInt(); }
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); }
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); }
public override void Goto(StreamLabel label) { uint offset = (uint)label - positionInStream; if (offset > (uint)endPosition) { positionInStream = (uint)label; position = endPosition = 0; } else position = (int)offset; }
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); }
/// <summary> /// Implementation of IStreamReader /// </summary> public virtual void Goto(StreamLabel label) { Debug.Assert(label != StreamLabel.Invalid); if (SerializationConfiguration.StreamLabelWidth == StreamLabelWidth.FourBytes) { Debug.Assert((long)label <= int.MaxValue); position = (uint)label; } else { position = (long)label; } }
public override void Goto(StreamLabel label) { uint offset = (uint)label - positionInStream; if (offset > (uint)endPosition) { positionInStream = (uint)label; position = endPosition = 0; } else { position = (int)offset; } }
public override bool Process() { while (_deserializer.Current < _endOfEventStream) { StreamLabel eventStart = _deserializer.Current; // Read the size of the next event. uint eventSize = (uint)_deserializer.ReadInt(); ReadAndDispatchTraceEvent(eventStart, eventSize); } sessionEndTimeQPC = (long)_lastTimestamp; return(true); }
/// <summary> /// Implementation of IStreamReader /// </summary> public override void Goto(StreamLabel label) { uint offset = unchecked ((uint)label - positionInStream); if (offset > (uint)endPosition) { if (!inputStream.CanSeek) { if ((uint)label < positionInStream + endPosition) { throw new Exception("Stream does not support seeking backwards"); } } positionInStream = (uint)label; position = endPosition = 0; } else { position = (int)offset; } }
/// <summary> /// Implementation of IStreamReader /// </summary> public override void Goto(StreamLabel label) { long offset = (long)label - positionInStream; if (offset > endPosition || offset < 0) { if (!inputStream.CanSeek) { if ((long)label < positionInStream + endPosition) { throw new Exception("Stream does not support seeking backwards"); } } positionInStream = (long)label & ~(align - 1); position = (int)((long)label & (align - 1)); endPosition = 0; } else { position = (int)offset; } }
public virtual void Goto(StreamLabel label) { Debug.Assert(label != StreamLabel.Invalid); position = (int)label; }
/// <summary> /// Get a byte* pointer to the input buffer at 'Position' in the IReadStream that is at least 'length' bytes long. /// (thus ptr to ptr+len is valid). Note that length cannot be larger than the buffer size passed to the reader /// when it was constructed. /// </summary> public unsafe byte *GetPointer(StreamLabel Position, int length) { Goto(Position); return(GetPointer(length)); }
/// <summary> /// Implementation of IStreamReader /// </summary> public virtual void Goto(StreamLabel label) { Debug.Assert(label != StreamLabel.Invalid); position = (int)label; }
public void WriteSuffixLabel(StreamLabel value) { // This is guarenteed to be uncompressed, but since we are not compressing anything, we can // simply write the value. Write(value); }
public void Write(StreamLabel value) { Write((int)value); }
public virtual void Goto(StreamLabel label) { position = (int)label; }
/// <summary> /// Creates a new MetaData instance from the serialized data at the current position of 'reader' /// of length 'length'. This typically points at the PAYLOAD AREA of a meta-data events) /// 'fileFormatVersionNumber' is the version number of the file as a whole /// (since that affects the parsing of this data) and 'processID' is the process ID for the /// whole stream (since it needs to be put into the EVENT_RECORD. /// /// When this constructor returns the reader has read all data given to it (thus it has /// move the read pointer by 'length') /// </summary> public EventPipeEventMetaData(PinnedStreamReader reader, int length, int fileFormatVersionNumber, int pointerSize, int processId) { StreamLabel eventDataEnd = reader.Current.Add(length); _eventRecord = (TraceEventNativeMethods.EVENT_RECORD *)Marshal.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD)); ClearMemory(_eventRecord, sizeof(TraceEventNativeMethods.EVENT_RECORD)); if (pointerSize == 4) { _eventRecord->EventHeader.Flags = TraceEventNativeMethods.EVENT_HEADER_FLAG_32_BIT_HEADER; } else { _eventRecord->EventHeader.Flags = TraceEventNativeMethods.EVENT_HEADER_FLAG_64_BIT_HEADER; } _eventRecord->EventHeader.ProcessId = processId; StreamLabel metaDataStart = reader.Current; if (fileFormatVersionNumber == 1) { _eventRecord->EventHeader.ProviderId = reader.ReadGuid(); } else { ProviderName = reader.ReadNullTerminatedUnicodeString(); _eventRecord->EventHeader.ProviderId = GetProviderGuidFromProviderName(ProviderName); } var eventId = (ushort)reader.ReadInt32(); _eventRecord->EventHeader.Id = eventId; Debug.Assert(_eventRecord->EventHeader.Id == eventId); // No truncation var version = reader.ReadInt32(); _eventRecord->EventHeader.Version = (byte)version; Debug.Assert(_eventRecord->EventHeader.Version == version); // No truncation if (fileFormatVersionNumber >= 3) { long keywords = reader.ReadInt64(); _eventRecord->EventHeader.Keyword = (ulong)keywords; } int metadataLength = reader.ReadInt32(); Debug.Assert(0 <= metadataLength && metadataLength < length); if (0 < metadataLength) { // TODO why do we repeat the event number it is redundant. eventId = (ushort)reader.ReadInt32(); Debug.Assert(_eventRecord->EventHeader.Id == eventId); // No truncation EventName = reader.ReadNullTerminatedUnicodeString(); Debug.Assert(EventName.Length < length / 2); // Deduce the opcode from the name. if (EventName.EndsWith("Start", StringComparison.OrdinalIgnoreCase)) { _eventRecord->EventHeader.Opcode = (byte)TraceEventOpcode.Start; } else if (EventName.EndsWith("Stop", StringComparison.OrdinalIgnoreCase)) { _eventRecord->EventHeader.Opcode = (byte)TraceEventOpcode.Stop; } _eventRecord->EventHeader.Keyword = (ulong)reader.ReadInt64(); // TODO why do we repeat the event number it is redundant. version = reader.ReadInt32(); Debug.Assert(_eventRecord->EventHeader.Version == version); // No truncation _eventRecord->EventHeader.Level = (byte)reader.ReadInt32(); Debug.Assert(_eventRecord->EventHeader.Level <= 5); // Fetch the parameter information int parameterCount = reader.ReadInt32(); Debug.Assert(0 <= parameterCount && parameterCount < length / 8); // Each parameter takes at least 8 bytes. if (parameterCount > 0) { ParameterDefinitions = new Tuple <TypeCode, string> [parameterCount]; for (int i = 0; i < parameterCount; i++) { var type = (TypeCode)reader.ReadInt32(); Debug.Assert((uint)type < 24); // There only a handful of type codes. var name = reader.ReadNullTerminatedUnicodeString(); ParameterDefinitions[i] = new Tuple <TypeCode, string>(type, name); Debug.Assert(reader.Current <= eventDataEnd); } } } Debug.Assert(reader.Current == eventDataEnd); }
public void Write(StreamLabel value) { Write((int)value); }
private void ReadAndUpdateEventMetadataDictionary(StreamLabel eventStart) { var eventMetadata = new EventMetadata(); // Skip the EventPipeEvent common fields which are not related to metedata int commonFieldSize = sizeof(int) // ThreadId + sizeof(Int64) // Timestamp + sizeof(Guid) // ActivityId + sizeof(Guid); // RelatedActivityId _deserializer.Goto(_deserializer.Current + (uint)commonFieldSize); // Read the event payload size. var payloadSize = _deserializer.ReadInt(); Debug.Assert(payloadSize >= 0, "Payload size should not be negative."); if (_version == 1) { var providerId = Guid.Empty; _deserializer.Read(out providerId); eventMetadata.ProviderId = providerId; } else { eventMetadata.ProviderName = _deserializer.ReadNullTerminatedUnicodeString(); } eventMetadata.EventId = (uint)_deserializer.ReadInt(); eventMetadata.Version = (uint)_deserializer.ReadInt(); var metadataPayloadLength = (uint)_deserializer.ReadInt(); if (metadataPayloadLength > 0) { var payloadIdentifierLength = 0; if (_version == 1) { payloadIdentifierLength = sizeof(Guid); } else { payloadIdentifierLength = (eventMetadata.ProviderName.Length + 1) * sizeof(Char); // +1 for null-terminator } var actualPayloadSize = payloadIdentifierLength + sizeof(int) // EventId + sizeof(int) // Version + sizeof(int) // MetadataPayloadLength + metadataPayloadLength; Debug.Assert(payloadSize == actualPayloadSize, $"The total event payload size is {actualPayloadSize}. But it is expected to be {payloadSize}."); // Read EventSource definition: https://github.com/dotnet/coreclr/blob/release/2.0.0/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs#L708 eventMetadata.EventId = (uint)_deserializer.ReadInt(); eventMetadata.EventName = _deserializer.ReadNullTerminatedUnicodeString(); eventMetadata.Keywords = (ulong)_deserializer.ReadInt64(); eventMetadata.Version = (uint)_deserializer.ReadInt(); eventMetadata.Level = (uint)_deserializer.ReadInt(); int parameterCount = _deserializer.ReadInt(); Debug.Assert(parameterCount >= 0, "Parameter count should not be negative."); if (parameterCount > 0) { eventMetadata.ParameterDefinitions = new Tuple <TypeCode, string> [parameterCount]; for (int i = 0; i < parameterCount; i++) { var type = (uint)_deserializer.ReadInt(); var name = _deserializer.ReadNullTerminatedUnicodeString(); eventMetadata.ParameterDefinitions[i] = new Tuple <TypeCode, string>((TypeCode)type, name); } } // add a new template to event parser _eventParser.AddTemplate(eventMetadata); } // Add the new event meta data into dictionary _eventMetadataDictionary.Add(eventStart, eventMetadata); // Read and verify stack size _deserializer.ReadIntAndVerify(0); }
public unsafe TraceEventNativeMethods.EVENT_RECORD* GetPointer(StreamLabel Position, int length) { Goto(Position); return GetPointer(length); }
/// <summary> /// Implementation of IStreamReader /// </summary> public virtual void Goto(StreamLabel label) { Debug.Assert(label != StreamLabel.Invalid); Debug.Assert((long)label <= int.MaxValue); position = (int)label; }
public virtual void Goto(StreamLabel label) { position = (int)label; }
/// <summary> /// Implementation of IStreamWriter /// </summary> public void Write(StreamLabel value) { Debug.Assert((long)value <= int.MaxValue); Write((int)value); }
public void WriteSuffixLabel(StreamLabel value) { // This is guarenteed to be uncompressed, but since we are not compressing anything, we can // simply write the value. Write(value); }
public unsafe byte* GetPointer(StreamLabel Position, int length) { Goto(Position); return GetPointer(length); }
public unsafe TraceEventNativeMethods.EVENT_RECORD *GetPointer(StreamLabel Position, int length) { Goto(Position); return(GetPointer(length)); }
/// <summary> /// Implementation of IStreamWriter /// </summary> public void Write(StreamLabel value) { writeLabel(value); }