private DynamicTraceEventData NewTemplate(Guid providerId, string providerName, uint eventId, string eventName, Tuple <TypeCode, string>[] parameterDefinitions) { int opcode; string opcodeName; GetOpcodeFromEventName(eventName, out opcode, out opcodeName); var template = new DynamicTraceEventData(null, (int)eventId, 0, eventName, Guid.Empty, opcode, opcodeName, providerId, providerName); if (parameterDefinitions != null && parameterDefinitions.Length > 0) { template.payloadNames = new string[parameterDefinitions.Length]; template.payloadFetches = new DynamicTraceEventData.PayloadFetch[parameterDefinitions.Length]; ushort offset = 0; for (int i = 0; i < parameterDefinitions.Length; i++) { template.payloadNames[i] = parameterDefinitions[i].Item2; var fetch = new DynamicTraceEventData.PayloadFetch(); switch (parameterDefinitions[i].Item1) { case TypeCode.Boolean: { fetch.Type = typeof(bool); fetch.Size = 4; // We follow windows conventions and use 4 bytes for bool. fetch.Offset = offset; break; } case TypeCode.Char: { fetch.Type = typeof(char); fetch.Size = sizeof(char); fetch.Offset = offset; break; } case TypeCode.SByte: { fetch.Type = typeof(SByte); fetch.Size = sizeof(SByte); fetch.Offset = offset; break; } case TypeCode.Byte: { fetch.Type = typeof(byte); fetch.Size = sizeof(byte); fetch.Offset = offset; break; } case TypeCode.Int16: { fetch.Type = typeof(Int16); fetch.Size = sizeof(Int16); fetch.Offset = offset; break; } case TypeCode.UInt16: { fetch.Type = typeof(UInt16); fetch.Size = sizeof(UInt16); fetch.Offset = offset; break; } case TypeCode.Int32: { fetch.Type = typeof(Int32); fetch.Size = sizeof(Int32); fetch.Offset = offset; break; } case TypeCode.UInt32: { fetch.Type = typeof(UInt32); fetch.Size = sizeof(UInt32); fetch.Offset = offset; break; } case TypeCode.Int64: { fetch.Type = typeof(Int64); fetch.Size = sizeof(Int64); fetch.Offset = offset; break; } case TypeCode.UInt64: { fetch.Type = typeof(UInt64); fetch.Size = sizeof(UInt64); fetch.Offset = offset; break; } case TypeCode.Single: { fetch.Type = typeof(Single); fetch.Size = sizeof(Single); fetch.Offset = offset; break; } case TypeCode.Double: { fetch.Type = typeof(Double); fetch.Size = sizeof(Double); fetch.Offset = offset; break; } case TypeCode.Decimal: { fetch.Type = typeof(Decimal); fetch.Size = sizeof(Decimal); fetch.Offset = offset; break; } case TypeCode.DateTime: { fetch.Type = typeof(DateTime); fetch.Size = 8; fetch.Offset = offset; break; } case TypeCode.String: { fetch.Type = typeof(String); fetch.Size = DynamicTraceEventData.NULL_TERMINATED; fetch.Offset = offset; break; } default: { throw new NotSupportedException($"{parameterDefinitions[i].Item1} is not supported."); } } if (fetch.Size >= DynamicTraceEventData.SPECIAL_SIZES || offset == ushort.MaxValue) { offset = ushort.MaxValue; // Indicate that the offset must be computed at run time. } else { offset += fetch.Size; } template.payloadFetches[i] = fetch; } } else { template.payloadNames = new string[0]; template.payloadFetches = new DynamicTraceEventData.PayloadFetch[0]; } return(template); }
private DynamicTraceEventData.PayloadFetchClassInfo ParseFields(PinnedStreamReader reader, int numFields) { string[] fieldNames = new string[numFields]; DynamicTraceEventData.PayloadFetch[] fieldFetches = new DynamicTraceEventData.PayloadFetch[numFields]; ushort offset = 0; for (int fieldIndex = 0; fieldIndex < numFields; fieldIndex++) { DynamicTraceEventData.PayloadFetch payloadFetch = new DynamicTraceEventData.PayloadFetch(); // Read the TypeCode for the current field. TypeCode typeCode = (TypeCode)reader.ReadInt32(); // Fill out the payload fetch object based on the TypeCode. switch (typeCode) { case TypeCode.Boolean: { payloadFetch.Type = typeof(bool); payloadFetch.Size = 4; // We follow windows conventions and use 4 bytes for bool. payloadFetch.Offset = offset; break; } case TypeCode.Char: { payloadFetch.Type = typeof(char); payloadFetch.Size = sizeof(char); payloadFetch.Offset = offset; break; } case TypeCode.SByte: { payloadFetch.Type = typeof(SByte); payloadFetch.Size = sizeof(SByte); payloadFetch.Offset = offset; break; } case TypeCode.Byte: { payloadFetch.Type = typeof(byte); payloadFetch.Size = sizeof(byte); payloadFetch.Offset = offset; break; } case TypeCode.Int16: { payloadFetch.Type = typeof(Int16); payloadFetch.Size = sizeof(Int16); payloadFetch.Offset = offset; break; } case TypeCode.UInt16: { payloadFetch.Type = typeof(UInt16); payloadFetch.Size = sizeof(UInt16); payloadFetch.Offset = offset; break; } case TypeCode.Int32: { payloadFetch.Type = typeof(Int32); payloadFetch.Size = sizeof(Int32); payloadFetch.Offset = offset; break; } case TypeCode.UInt32: { payloadFetch.Type = typeof(UInt32); payloadFetch.Size = sizeof(UInt32); payloadFetch.Offset = offset; break; } case TypeCode.Int64: { payloadFetch.Type = typeof(Int64); payloadFetch.Size = sizeof(Int64); payloadFetch.Offset = offset; break; } case TypeCode.UInt64: { payloadFetch.Type = typeof(UInt64); payloadFetch.Size = sizeof(UInt64); payloadFetch.Offset = offset; break; } case TypeCode.Single: { payloadFetch.Type = typeof(Single); payloadFetch.Size = sizeof(Single); payloadFetch.Offset = offset; break; } case TypeCode.Double: { payloadFetch.Type = typeof(Double); payloadFetch.Size = sizeof(Double); payloadFetch.Offset = offset; break; } case TypeCode.Decimal: { payloadFetch.Type = typeof(Decimal); payloadFetch.Size = sizeof(Decimal); payloadFetch.Offset = offset; break; } case TypeCode.DateTime: { payloadFetch.Type = typeof(DateTime); payloadFetch.Size = 8; payloadFetch.Offset = offset; break; } case EventPipeEventSource.GuidTypeCode: { payloadFetch.Type = typeof(Guid); payloadFetch.Size = 16; payloadFetch.Offset = offset; break; } case TypeCode.String: { payloadFetch.Type = typeof(String); payloadFetch.Size = DynamicTraceEventData.NULL_TERMINATED; payloadFetch.Offset = offset; break; } case TypeCode.Object: { // TypeCode.Object represents an embedded struct. // Read the number of fields in the struct. Each of these fields could be an embedded struct, // but these embedded structs are still counted as single fields. They will be expanded when they are handled. int structFieldCount = reader.ReadInt32(); DynamicTraceEventData.PayloadFetchClassInfo embeddedStructClassInfo = ParseFields(reader, structFieldCount); if (embeddedStructClassInfo == null) { throw new Exception("Unable to parse metadata for embedded struct."); } payloadFetch = DynamicTraceEventData.PayloadFetch.StructPayloadFetch(offset, embeddedStructClassInfo); break; } default: { throw new NotSupportedException($"{typeCode} is not supported."); } } // Read the string name of the event payload field. fieldNames[fieldIndex] = reader.ReadNullTerminatedUnicodeString(); // Update the offset into the event for the next payload fetch. if (payloadFetch.Size >= DynamicTraceEventData.SPECIAL_SIZES || offset == ushort.MaxValue) { offset = ushort.MaxValue; // Indicate that the offset must be computed at run time. } else { offset += payloadFetch.Size; } // Save the current payload fetch. fieldFetches[fieldIndex] = payloadFetch; } return(new DynamicTraceEventData.PayloadFetchClassInfo() { FieldNames = fieldNames, FieldFetches = fieldFetches }); }