Skip to content

Commit 9ea4ec5

Browse files
committed
Fix endian serialization for eventpipe libraries
1 parent e1eacef commit 9ea4ec5

13 files changed

Lines changed: 399 additions & 142 deletions

src/FastSerialization/FastSerialization.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
using System.Diagnostics;
1010
using System.IO;
1111
using System.Text; // For StringBuilder.
12-
12+
using System.Buffers.Binary;
13+
using System.Runtime.InteropServices;
1314
// see #Introduction and #SerializerIntroduction
1415
namespace FastSerialization
1516
{
@@ -590,7 +591,6 @@ public Serializer(IStreamWriter writer, IFastSerializable entryObject)
590591
Log("<Serializer>");
591592
// Write the header.
592593
Write("!FastSerialization.1");
593-
594594
// Write the main object. This is recursive and does most of the work.
595595
Write(entryObject);
596596

@@ -605,7 +605,7 @@ public Serializer(IStreamWriter writer, IFastSerializable entryObject)
605605
Log("<ForwardRefTable StreamLabel=\"0x" + forwardRefsLabel.ToString("x") + "\">");
606606
if (forwardReferenceDefinitions != null)
607607
{
608-
Write(forwardReferenceDefinitions.Count);
608+
Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(forwardReferenceDefinitions.Count)));
609609
for (int i = 0; i < forwardReferenceDefinitions.Count; i++)
610610
{
611611
Debug.Assert(forwardReferenceDefinitions[i] != StreamLabel.Invalid);
@@ -688,7 +688,15 @@ public void Write(long value)
688688
public void Write(Guid value)
689689
{
690690
Log("<Write Type=\"Guid\" Value=\"" + value + "\" StreamLabel=\"0x" + writer.GetLabel().ToString("x") + "\"/>");
691-
byte[] bytes = value.ToByteArray();
691+
Span<byte> bytes = value.ToByteArray();
692+
693+
if (!BitConverter.IsLittleEndian)
694+
{
695+
BinaryPrimitives.WriteInt32LittleEndian(bytes.Slice(0), (MemoryMarshal.Read<int>(bytes.Slice(0,4))));
696+
BinaryPrimitives.WriteInt16LittleEndian(bytes.Slice(4), (MemoryMarshal.Read<short>(bytes.Slice(4,6))));
697+
BinaryPrimitives.WriteInt16LittleEndian(bytes.Slice(6), (MemoryMarshal.Read<short>(bytes.Slice(6,8))));
698+
}
699+
692700
for (int i = 0; i < bytes.Length; i++)
693701
{
694702
writer.Write(bytes[i]);
@@ -815,15 +823,15 @@ public void DefineForwardReference(ForwardReference forwardReference)
815823
/// <summary>
816824
/// Write a byte preceded by a tag that indicates its a short. These should be read with the corresponding TryReadTagged operation
817825
/// </summary>
818-
public void WriteTagged(short value) { WriteTag(Tags.Int16); Write(value); }
826+
public void WriteTagged(short value) { WriteTag(Tags.Int16); Write(BinaryPrimitives.ReadInt16LittleEndian(BitConverter.GetBytes(value))); }
819827
/// <summary>
820828
/// Write a byte preceded by a tag that indicates its a int. These should be read with the corresponding TryReadTagged operation
821829
/// </summary>
822-
public void WriteTagged(int value) { WriteTag(Tags.Int32); Write(value); }
830+
public void WriteTagged(int value) { WriteTag(Tags.Int32); Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(value))); }
823831
/// <summary>
824832
/// Write a byte preceded by a tag that indicates its a long. These should be read with the corresponding TryReadTagged operation
825833
/// </summary>
826-
public void WriteTagged(long value) { WriteTag(Tags.Int64); Write(value); }
834+
public void WriteTagged(long value) { WriteTag(Tags.Int64); Write(BinaryPrimitives.ReadInt64LittleEndian(BitConverter.GetBytes(value))); }
827835
/// <summary>
828836
/// Write a byte preceded by a tag that indicates its a string. These should be read with the corresponding TryReadTagged operation
829837
/// </summary>
@@ -1591,7 +1599,6 @@ public StreamLabel ResolveForwardReference(ForwardReference reference, bool pres
15911599
reader.GotoSuffixLabel();
15921600
Log("<Trailer StreamLabel=\"0x" + reader.Current.ToString("x") + "\"/>");
15931601
StreamLabel forwardRefsLabel = reader.ReadLabel();
1594-
15951602
Goto(forwardRefsLabel);
15961603
int fowardRefCount = reader.ReadInt32();
15971604
Log("<ForwardReferenceDefinitons StreamLabel=\"0x" + forwardRefsLabel.ToString("x") +
@@ -2226,7 +2233,7 @@ public void Write(Serializer serializer, Action toStream)
22262233
serializer.Log("<DeferedRegion>\r\n");
22272234
// We actually don't use the this pointer! We did this for symmetry with Read
22282235
ForwardReference endRegion = serializer.GetForwardReference();
2229-
serializer.Write(endRegion); // Allow the reader to skip this.
2236+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes((int)endRegion))); // Allow the reader to skip this.
22302237
toStream(); // Write the deferred data.
22312238
serializer.DefineForwardReference(endRegion);
22322239
serializer.Log("</DeferedRegion>\r\n");
@@ -2503,8 +2510,8 @@ internal SerializationType(string fullName, Deserializer deserializer)
25032510
}
25042511
void IFastSerializable.ToStream(Serializer serializer)
25052512
{
2506-
serializer.Write(version);
2507-
serializer.Write(minimumReaderVersion);
2513+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(version)));
2514+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(minimumReaderVersion)));
25082515
serializer.Write(fullName);
25092516
}
25102517
void IFastSerializable.FromStream(Deserializer deserializer)

src/FastSerialization/FastSerialization.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
3030
</ItemGroup>
3131

32+
<ItemGroup>
33+
<PackageReference Include="System.Memory"/>
34+
</ItemGroup>
35+
3236
<!-- ******************* Signing Support *********************** -->
3337
<ItemGroup>
3438
<FilesToSign Include="$(TargetPath)">

src/FastSerialization/StreamReaderWriter.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Diagnostics;
99
using System.IO;
1010
using System.Text; // For StringBuilder.
11+
using System.Buffers.Binary;
1112

1213
namespace FastSerialization
1314
{
@@ -259,15 +260,15 @@ public MemoryStreamWriter(SerializationSettings settings, int initialSize = 64)
259260
writeLabel = (value) =>
260261
{
261262
Debug.Assert((long)value <= int.MaxValue);
262-
Write((int)value);
263+
Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes((int)value)));
263264
};
264265
}
265266
else
266267
{
267268
writeLabel = (value) =>
268269
{
269270
Debug.Assert((long)value <= long.MaxValue);
270-
Write((long)value);
271+
Write(BinaryPrimitives.ReadInt64LittleEndian(BitConverter.GetBytes((long)value)));
271272
};
272273
}
273274

@@ -392,7 +393,7 @@ public void Write(string value)
392393
}
393394
else
394395
{
395-
Write(value.Length);
396+
Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(value.Length)));
396397
for (int i = 0; i < value.Length; i++)
397398
{
398399
char c = value[i];

src/TraceEvent/DynamicTraceEventParser.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
using System.Text.RegularExpressions;
1313
using System.Xml;
1414
using Address = System.UInt64;
15-
15+
using System.Buffers.Binary;
1616
namespace Microsoft.Diagnostics.Tracing.Parsers
1717
{
1818
/// <summary>
@@ -1830,11 +1830,11 @@ public override string ToString()
18301830

18311831
public void ToStream(Serializer serializer)
18321832
{
1833-
serializer.Write((int)eventID);
1834-
serializer.Write((int)task);
1833+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes((int)eventID)));
1834+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes((int)task)));
18351835
serializer.Write(taskName);
18361836
serializer.Write(taskGuid);
1837-
serializer.Write((int)opcode);
1837+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes((int)opcode)));
18381838
serializer.Write(opcodeName);
18391839
serializer.Write(providerGuid);
18401840
serializer.Write(providerName);
@@ -1843,13 +1843,13 @@ public void ToStream(Serializer serializer)
18431843
serializer.Write(lookupAsWPP);
18441844
serializer.Write(containsSelfDescribingMetadata);
18451845

1846-
serializer.Write(payloadNames.Length);
1846+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(payloadNames.Length)));
18471847
foreach (var payloadName in payloadNames)
18481848
{
18491849
serializer.Write(payloadName);
18501850
}
18511851

1852-
serializer.Write(payloadFetches.Length);
1852+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(payloadFetches.Length)));
18531853
foreach (var payloadFetch in payloadFetches)
18541854
{
18551855
payloadFetch.ToStream(serializer);
@@ -1983,7 +1983,7 @@ internal class DynamicTraceEventParserState : IFastSerializable
19831983

19841984
void IFastSerializable.ToStream(Serializer serializer)
19851985
{
1986-
serializer.Write(providers.Count);
1986+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(providers.Count)));
19871987
foreach (ProviderManifest provider in providers.Values)
19881988
{
19891989
serializer.Write(provider);

src/TraceEvent/EventPipe/EventPipeEventSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ internal void ReadMetadataBlockV6OrGreater(Block block)
275275
internal void ReadMetadataBlockV5OrLess(Block block)
276276
{
277277
SpanReader metadataReader = block.Reader;
278-
278+
279279
short headerSize = metadataReader.ReadInt16();
280280
if(headerSize < 20)
281281
{

src/TraceEvent/EventPipe/RewindableStream.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System.Reflection;
66
using System.Runtime.CompilerServices;
77
using System.Runtime.InteropServices;
8-
8+
using System.Buffers.Binary;
99
namespace Microsoft.Diagnostics.Tracing.EventPipe
1010
{
1111

@@ -60,6 +60,40 @@ public T Read<T>() where T : struct
6060
{
6161
Span<byte> buffer = stackalloc byte[Unsafe.SizeOf<T>()];
6262
Read(buffer);
63+
if (!BitConverter.IsLittleEndian)
64+
{
65+
if(typeof(T) == typeof(short))
66+
{
67+
short val = BinaryPrimitives.ReadInt16LittleEndian(buffer);
68+
return (T)(object)val;
69+
}
70+
else if(typeof(T) == typeof(int))
71+
{
72+
int val = BinaryPrimitives.ReadInt32LittleEndian(buffer);
73+
return (T)(object)val;
74+
}
75+
else if(typeof(T) == typeof(long))
76+
{
77+
long val = BinaryPrimitives.ReadInt64LittleEndian(buffer);
78+
return (T)(object)val;
79+
}
80+
else if(typeof(T) == typeof(ushort))
81+
{
82+
ushort val = BinaryPrimitives.ReadUInt16LittleEndian(buffer);
83+
return (T)(object)val;
84+
}
85+
else if(typeof(T) == typeof(uint))
86+
{
87+
uint val = BinaryPrimitives.ReadUInt32LittleEndian(buffer);
88+
return (T)(object)val;
89+
}
90+
else if(typeof(T) == typeof(ulong))
91+
{
92+
ulong val = BinaryPrimitives.ReadUInt64LittleEndian(buffer);
93+
return (T)(object)val;
94+
}
95+
96+
}
6397
return MemoryMarshal.Read<T>(buffer);
6498
}
6599

src/TraceEvent/EventPipe/SpanReader.cs

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Runtime.CompilerServices;
33
using System.Runtime.InteropServices;
44
using System.Text;
5-
5+
using System.Buffers.Binary;
66
namespace Microsoft.Diagnostics.Tracing.EventPipe
77
{
88
ref struct SpanReader
@@ -21,12 +21,90 @@ public SpanReader(ReadOnlySpan<byte> buffer, long spanStartStreamOffset)
2121

2222
public sbyte ReadInt8() => Read<sbyte>();
2323
public byte ReadUInt8() => Read<byte>();
24-
public short ReadInt16() => Read<short>();
25-
public ushort ReadUInt16() => Read<ushort>();
26-
public int ReadInt32() => Read<int>();
27-
public uint ReadUInt32() => Read<uint>();
28-
public long ReadInt64() => Read<long>();
29-
public ulong ReadUInt64() => Read<ulong>();
24+
25+
public short ReadInt16()
26+
{
27+
short val;
28+
if (BinaryPrimitives.TryReadInt16LittleEndian(_buffer, out val))
29+
{
30+
_buffer = _buffer.Slice(sizeof(short));
31+
}
32+
else
33+
{
34+
ThrowFormatException<short>();
35+
}
36+
return val;
37+
}
38+
39+
public ushort ReadUInt16()
40+
{
41+
ushort val;
42+
if (BinaryPrimitives.TryReadUInt16LittleEndian(_buffer, out val))
43+
{
44+
_buffer = _buffer.Slice(sizeof(ushort));
45+
}
46+
else
47+
{
48+
ThrowFormatException<ushort>();
49+
}
50+
return val;
51+
}
52+
53+
public int ReadInt32()
54+
{
55+
int val;
56+
if (BinaryPrimitives.TryReadInt32LittleEndian(_buffer, out val))
57+
{
58+
_buffer = _buffer.Slice(sizeof(int));
59+
}
60+
else
61+
{
62+
ThrowFormatException<int>();
63+
}
64+
return val;
65+
}
66+
67+
public uint ReadUInt32()
68+
{
69+
uint val;
70+
if (BinaryPrimitives.TryReadUInt32LittleEndian(_buffer, out val))
71+
{
72+
_buffer = _buffer.Slice(sizeof(uint));
73+
}
74+
else
75+
{
76+
ThrowFormatException<uint>();
77+
}
78+
return val;
79+
}
80+
81+
public long ReadInt64()
82+
{
83+
long val;
84+
if (BinaryPrimitives.TryReadInt64LittleEndian(_buffer, out val))
85+
{
86+
_buffer = _buffer.Slice(sizeof(long));
87+
}
88+
else
89+
{
90+
ThrowFormatException<long>();
91+
}
92+
return val;
93+
}
94+
95+
public ulong ReadUInt64()
96+
{
97+
ulong val;
98+
if (BinaryPrimitives.TryReadUInt64LittleEndian(_buffer, out val))
99+
{
100+
_buffer = _buffer.Slice(sizeof(ulong));
101+
}
102+
else
103+
{
104+
ThrowFormatException<ulong>();
105+
}
106+
return val;
107+
}
30108

31109
public T Read<T>() where T : struct
32110
{
@@ -156,7 +234,17 @@ public string ReadVarUIntUTF8String()
156234

157235
public string ReadNullTerminatedUTF16String()
158236
{
159-
ReadOnlySpan<char> charBuffer = MemoryMarshal.Cast<byte, char>(_buffer);
237+
238+
ReadOnlySpan<char> Buffer = MemoryMarshal.Cast<byte, char>(_buffer);
239+
Span<char> charBuffer = stackalloc char [Buffer.Length];
240+
Buffer.CopyTo(charBuffer);
241+
if (!BitConverter.IsLittleEndian)
242+
{
243+
for(int ii = 0; ii < charBuffer.Length; ii++)
244+
{
245+
charBuffer[ii] = (char)BinaryPrimitives.ReverseEndianness((ushort)charBuffer[ii]);
246+
}
247+
}
160248
for(int i = 0; i < charBuffer.Length; i++)
161249
{
162250
if (charBuffer[i] == 0)

src/TraceEvent/RegisteredTraceEventParser.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
using System.Text;
1212
using System.Text.RegularExpressions;
1313
using System.Xml;
14-
14+
using System.Buffers.Binary;
1515
namespace Microsoft.Diagnostics.Tracing.Parsers
1616
{
1717
/// <summary>
@@ -1567,7 +1567,7 @@ public virtual void ToStream(Serializer serializer)
15671567
}
15681568
}
15691569

1570-
serializer.Write(count);
1570+
serializer.Write(BinaryPrimitives.ReadInt32LittleEndian(BitConverter.GetBytes(count)));
15711571
foreach (var template in m_templates.Values)
15721572
{
15731573
if (template != null)

src/TraceEvent/Stacks/SpeedScopeStackSourceWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ private static void Export(StackSource source, TextWriter writer, string name)
4242
};
4343

4444
var orderedFrameNames = exportedFrameNameToExportedFrameId.OrderBy(pair => pair.Value).Select(pair => pair.Key).ToArray();
45-
45+
4646
WriteToFile(profileEventsPerThread, orderedFrameNames, writer, name);
4747
}
4848

0 commit comments

Comments
 (0)