diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index dee4b5ac0f5fd..a6733de763a57 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -18,6 +18,7 @@ using Microsoft.CodeAnalysis.CSharp; using System.Reflection; using System.Text; +using System.Runtime.CompilerServices; namespace Microsoft.WebAssembly.Diagnostics { @@ -385,20 +386,6 @@ public MonoBinaryReader(Stream stream, bool hasError = false) : base(stream) HasError = hasError; } - internal static unsafe void PutBytesBE (byte *dest, byte *src, int count) - { - int i = 0; - - if (BitConverter.IsLittleEndian){ - dest += count; - for (; i < count; i++) - *(--dest) = *src++; - } else { - for (; i < count; i++) - *dest++ = *src++; - } - } - public override string ReadString() { var valueLen = ReadInt32(); @@ -407,108 +394,58 @@ public override string ReadString() return new string(Encoding.UTF8.GetChars(value, 0, valueLen)); } - public unsafe long ReadLong() - { - byte[] data = new byte[8]; - Read(data, 0, 8); - long ret; - fixed (byte *src = &data[0]){ - PutBytesBE ((byte *) &ret, src, 8); - } - - return ret; - } - public override unsafe sbyte ReadSByte() - { - byte[] data = new byte[4]; - Read(data, 0, 4); + // SDB encodes these as 4 bytes + public override sbyte ReadSByte() => (sbyte)ReadInt32(); + public byte ReadUByte() => (byte)ReadUInt32(); + public ushort ReadUShort() => (ushort)ReadUInt32(); + public override int ReadInt32() => ReadBigEndian(); - int ret; - fixed (byte *src = &data[0]){ - PutBytesBE ((byte *) &ret, src, 4); - } - return (sbyte)ret; - } - - public unsafe byte ReadUByte() - { - byte[] data = new byte[4]; - Read(data, 0, 4); - - int ret; - fixed (byte *src = &data[0]){ - PutBytesBE ((byte *) &ret, src, 4); - } - return (byte)ret; - } - - public override unsafe int ReadInt32() - { - byte[] data = new byte[4]; - Read(data, 0, 4); - int ret; - fixed (byte *src = &data[0]){ - PutBytesBE ((byte *) &ret, src, 4); - } - return ret; - } + public override double ReadDouble() => ReadBigEndian(); + public override uint ReadUInt32() => ReadBigEndian(); + public override float ReadSingle() => ReadBigEndian(); + public override ulong ReadUInt64() => ReadBigEndian(); + public override long ReadInt64() => ReadBigEndian(); - public override unsafe double ReadDouble() + protected unsafe T ReadBigEndian() where T : struct { - byte[] data = new byte[8]; - Read(data, 0, 8); - - double ret; - fixed (byte *src = &data[0]){ - PutBytesBE ((byte *) &ret, src, 8); - } - return ret; - } - - public override unsafe uint ReadUInt32() - { - byte[] data = new byte[4]; - Read(data, 0, 4); - - uint ret; - fixed (byte *src = &data[0]){ - PutBytesBE ((byte *) &ret, src, 4); + Span data = stackalloc byte[Unsafe.SizeOf()]; + T ret = default; + Read(data); + if (BitConverter.IsLittleEndian) + { + data.Reverse(); } + data.CopyTo(new Span(Unsafe.AsPointer(ref ret), data.Length)); return ret; } - public unsafe ushort ReadUShort() - { - byte[] data = new byte[4]; - Read(data, 0, 4); - - uint ret; - fixed (byte *src = &data[0]){ - PutBytesBE ((byte *) &ret, src, 4); - } - return (ushort)ret; - } } internal class MonoBinaryWriter : BinaryWriter { public MonoBinaryWriter(Stream stream) : base(stream) {} - public void WriteString(string val) - { - Write(val.Length); - Write(val.ToCharArray()); - } - public void WriteLong(long val) + + public override void Write(string val) { - Write((int)((val >> 32) & 0xffffffff)); - Write((int)((val >> 0) & 0xffffffff)); + var bytes = Encoding.UTF8.GetBytes(val); + Write(bytes.Length); + Write(bytes); } - public override void Write(int val) + + public override void Write(long val) => WriteBigEndian(val); + public override void Write(int val) => WriteBigEndian(val); + + protected unsafe void WriteBigEndian(T val) where T : struct { - byte[] bytes = BitConverter.GetBytes(val); - Array.Reverse(bytes, 0, bytes.Length); - Write(bytes); + Span data = stackalloc byte[Unsafe.SizeOf()]; + new Span(Unsafe.AsPointer(ref val), data.Length).CopyTo(data); + if (BitConverter.IsLittleEndian) + { + data.Reverse(); + } + base.Write(data); } + public void WriteObj(DotnetObjectId objectId, MonoSDBHelper SdbHelper) { if (objectId.Scheme == "object") @@ -878,7 +815,7 @@ public async Task CreateString(SessionId sessionId, string value, Cancellat var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAppDomain.GetRootDomain, commandParams, token); var root_domain = retDebuggerCmdReader.ReadInt32(); commandParamsWriter.Write(root_domain); - commandParamsWriter.WriteString(value); + commandParamsWriter.Write(value); retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAppDomain.CreateString, commandParams, token); return retDebuggerCmdReader.ReadInt32(); } @@ -989,7 +926,7 @@ public async Task GetAssemblyId(SessionId sessionId, string asm_name, Cance { var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); - commandParamsWriter.WriteString(asm_name); + commandParamsWriter.Write(asm_name); var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.GetAssemblyByName, commandParams, token); return retDebuggerCmdReader.ReadInt32(); @@ -1124,7 +1061,7 @@ public async Task SetBreakpoint(SessionId sessionId, int methodId, long il_ commandParamsWriter.Write((byte)1); commandParamsWriter.Write((byte)ModifierKind.LocationOnly); commandParamsWriter.Write(methodId); - commandParamsWriter.WriteLong(il_offset); + commandParamsWriter.Write(il_offset); var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); return retDebuggerCmdReader.ReadInt32(); } @@ -1509,7 +1446,7 @@ public async Task GetMethodIdByName(SessionId sessionId, int type_id, strin var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); commandParamsWriter.Write((int)type_id); - commandParamsWriter.WriteString(method_name); + commandParamsWriter.Write(method_name); commandParamsWriter.Write((int)(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)); commandParamsWriter.Write((int)1); //case sensitive var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetMethodsByNameFlags, commandParams, token); @@ -1645,7 +1582,7 @@ public async Task GetPointerContent(SessionId sessionId, int pointerId, var ret = new List(); var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); - commandParamsWriter.WriteLong(pointerValues[pointerId].address); + commandParamsWriter.Write(pointerValues[pointerId].address); commandParamsWriter.Write(pointerValues[pointerId].typeId); var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdPointer.GetValue, commandParams, token); var varName = pointerValues[pointerId].varName; @@ -1744,7 +1681,7 @@ public async Task CreateJObjectForPtr(SessionId sessionId, ElementType { string type; string value; - long valueAddress = retDebuggerCmdReader.ReadLong(); + long valueAddress = retDebuggerCmdReader.ReadInt64(); var typeId = retDebuggerCmdReader.ReadInt32(); var className = ""; if (etype == ElementType.FnPtr) @@ -1955,7 +1892,7 @@ public async Task CreateJObjectForVariableValue(SessionId sessionId, Mo } case ElementType.R4: { - float value = BitConverter.Int32BitsToSingle(retDebuggerCmdReader.ReadInt32()); + float value = retDebuggerCmdReader.ReadSingle(); ret = CreateJObjectForNumber(value); break; } @@ -1967,15 +1904,13 @@ public async Task CreateJObjectForVariableValue(SessionId sessionId, Mo } case ElementType.I8: { - long value = retDebuggerCmdReader.ReadLong(); + long value = retDebuggerCmdReader.ReadInt64(); ret = CreateJObjectForNumber(value); break; } case ElementType.U8: { - ulong high = (ulong) retDebuggerCmdReader.ReadInt32(); - ulong low = (ulong) retDebuggerCmdReader.ReadInt32(); - var value = ((high << 32) | low); + ulong value = retDebuggerCmdReader.ReadUInt64(); ret = CreateJObjectForNumber(value); break; } @@ -2257,7 +2192,7 @@ public async Task GetTypeByName(SessionId sessionId, string typeToSearch, C { var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); - commandParamsWriter.WriteString(typeToSearch); + commandParamsWriter.Write(typeToSearch); var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.GetTypes, commandParams, token); var count = retDebuggerCmdReader.ReadInt32(); //count ret return retDebuggerCmdReader.ReadInt32();