Skip to content

Commit

Permalink
[wasm][debugger] Correct the endian swapping and string implementation (
Browse files Browse the repository at this point in the history
#61386)

* [wasm][debugger[ Correct the endian swapping and string implementation
  • Loading branch information
lewing committed Nov 10, 2021
1 parent e64cce6 commit 45543cc
Showing 1 changed file with 47 additions and 112 deletions.
159 changes: 47 additions & 112 deletions src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Microsoft.CodeAnalysis.CSharp;
using System.Reflection;
using System.Text;
using System.Runtime.CompilerServices;

namespace Microsoft.WebAssembly.Diagnostics
{
Expand Down Expand Up @@ -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();
Expand All @@ -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>();

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<double>();
public override uint ReadUInt32() => ReadBigEndian<uint>();
public override float ReadSingle() => ReadBigEndian<float>();
public override ulong ReadUInt64() => ReadBigEndian<ulong>();
public override long ReadInt64() => ReadBigEndian<long>();

public override unsafe double ReadDouble()
protected unsafe T ReadBigEndian<T>() 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<byte> data = stackalloc byte[Unsafe.SizeOf<T>()];
T ret = default;
Read(data);
if (BitConverter.IsLittleEndian)
{
data.Reverse();
}
data.CopyTo(new Span<byte>(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<long>(val);
public override void Write(int val) => WriteBigEndian<int>(val);

protected unsafe void WriteBigEndian<T>(T val) where T : struct
{
byte[] bytes = BitConverter.GetBytes(val);
Array.Reverse(bytes, 0, bytes.Length);
Write(bytes);
Span<byte> data = stackalloc byte[Unsafe.SizeOf<T>()];
new Span<byte>(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")
Expand Down Expand Up @@ -878,7 +815,7 @@ public async Task<int> CreateString(SessionId sessionId, string value, Cancellat
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdAppDomain>(sessionId, CmdAppDomain.GetRootDomain, commandParams, token);
var root_domain = retDebuggerCmdReader.ReadInt32();
commandParamsWriter.Write(root_domain);
commandParamsWriter.WriteString(value);
commandParamsWriter.Write(value);
retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdAppDomain>(sessionId, CmdAppDomain.CreateString, commandParams, token);
return retDebuggerCmdReader.ReadInt32();
}
Expand Down Expand Up @@ -989,7 +926,7 @@ public async Task<int> 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<CmdVM>(sessionId, CmdVM.GetAssemblyByName, commandParams, token);
return retDebuggerCmdReader.ReadInt32();
Expand Down Expand Up @@ -1124,7 +1061,7 @@ public async Task<int> 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<CmdEventRequest>(sessionId, CmdEventRequest.Set, commandParams, token);
return retDebuggerCmdReader.ReadInt32();
}
Expand Down Expand Up @@ -1509,7 +1446,7 @@ public async Task<int> 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<CmdType>(sessionId, CmdType.GetMethodsByNameFlags, commandParams, token);
Expand Down Expand Up @@ -1645,7 +1582,7 @@ public async Task<JObject> GetPointerContent(SessionId sessionId, int pointerId,
var ret = new List<string>();
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<CmdPointer>(sessionId, CmdPointer.GetValue, commandParams, token);
var varName = pointerValues[pointerId].varName;
Expand Down Expand Up @@ -1744,7 +1681,7 @@ public async Task<JObject> 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)
Expand Down Expand Up @@ -1955,7 +1892,7 @@ public async Task<JObject> CreateJObjectForVariableValue(SessionId sessionId, Mo
}
case ElementType.R4:
{
float value = BitConverter.Int32BitsToSingle(retDebuggerCmdReader.ReadInt32());
float value = retDebuggerCmdReader.ReadSingle();
ret = CreateJObjectForNumber<float>(value);
break;
}
Expand All @@ -1967,15 +1904,13 @@ public async Task<JObject> CreateJObjectForVariableValue(SessionId sessionId, Mo
}
case ElementType.I8:
{
long value = retDebuggerCmdReader.ReadLong();
long value = retDebuggerCmdReader.ReadInt64();
ret = CreateJObjectForNumber<long>(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<ulong>(value);
break;
}
Expand Down Expand Up @@ -2257,7 +2192,7 @@ public async Task<int> 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<CmdVM>(sessionId, CmdVM.GetTypes, commandParams, token);
var count = retDebuggerCmdReader.ReadInt32(); //count ret
return retDebuggerCmdReader.ReadInt32();
Expand Down

0 comments on commit 45543cc

Please sign in to comment.