Skip to content

Commit 45543cc

Browse files
authored
[wasm][debugger] Correct the endian swapping and string implementation (#61386)
* [wasm][debugger[ Correct the endian swapping and string implementation
1 parent e64cce6 commit 45543cc

File tree

1 file changed

+47
-112
lines changed

1 file changed

+47
-112
lines changed

src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs

Lines changed: 47 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Microsoft.CodeAnalysis.CSharp;
1919
using System.Reflection;
2020
using System.Text;
21+
using System.Runtime.CompilerServices;
2122

2223
namespace Microsoft.WebAssembly.Diagnostics
2324
{
@@ -385,20 +386,6 @@ public MonoBinaryReader(Stream stream, bool hasError = false) : base(stream)
385386
HasError = hasError;
386387
}
387388

388-
internal static unsafe void PutBytesBE (byte *dest, byte *src, int count)
389-
{
390-
int i = 0;
391-
392-
if (BitConverter.IsLittleEndian){
393-
dest += count;
394-
for (; i < count; i++)
395-
*(--dest) = *src++;
396-
} else {
397-
for (; i < count; i++)
398-
*dest++ = *src++;
399-
}
400-
}
401-
402389
public override string ReadString()
403390
{
404391
var valueLen = ReadInt32();
@@ -407,108 +394,58 @@ public override string ReadString()
407394

408395
return new string(Encoding.UTF8.GetChars(value, 0, valueLen));
409396
}
410-
public unsafe long ReadLong()
411-
{
412-
byte[] data = new byte[8];
413-
Read(data, 0, 8);
414397

415-
long ret;
416-
fixed (byte *src = &data[0]){
417-
PutBytesBE ((byte *) &ret, src, 8);
418-
}
419-
420-
return ret;
421-
}
422-
public override unsafe sbyte ReadSByte()
423-
{
424-
byte[] data = new byte[4];
425-
Read(data, 0, 4);
398+
// SDB encodes these as 4 bytes
399+
public override sbyte ReadSByte() => (sbyte)ReadInt32();
400+
public byte ReadUByte() => (byte)ReadUInt32();
401+
public ushort ReadUShort() => (ushort)ReadUInt32();
402+
public override int ReadInt32() => ReadBigEndian<int>();
426403

427-
int ret;
428-
fixed (byte *src = &data[0]){
429-
PutBytesBE ((byte *) &ret, src, 4);
430-
}
431-
return (sbyte)ret;
432-
}
433-
434-
public unsafe byte ReadUByte()
435-
{
436-
byte[] data = new byte[4];
437-
Read(data, 0, 4);
438-
439-
int ret;
440-
fixed (byte *src = &data[0]){
441-
PutBytesBE ((byte *) &ret, src, 4);
442-
}
443-
return (byte)ret;
444-
}
445-
446-
public override unsafe int ReadInt32()
447-
{
448-
byte[] data = new byte[4];
449-
Read(data, 0, 4);
450-
int ret;
451-
fixed (byte *src = &data[0]){
452-
PutBytesBE ((byte *) &ret, src, 4);
453-
}
454-
return ret;
455-
}
404+
public override double ReadDouble() => ReadBigEndian<double>();
405+
public override uint ReadUInt32() => ReadBigEndian<uint>();
406+
public override float ReadSingle() => ReadBigEndian<float>();
407+
public override ulong ReadUInt64() => ReadBigEndian<ulong>();
408+
public override long ReadInt64() => ReadBigEndian<long>();
456409

457-
public override unsafe double ReadDouble()
410+
protected unsafe T ReadBigEndian<T>() where T : struct
458411
{
459-
byte[] data = new byte[8];
460-
Read(data, 0, 8);
461-
462-
double ret;
463-
fixed (byte *src = &data[0]){
464-
PutBytesBE ((byte *) &ret, src, 8);
465-
}
466-
return ret;
467-
}
468-
469-
public override unsafe uint ReadUInt32()
470-
{
471-
byte[] data = new byte[4];
472-
Read(data, 0, 4);
473-
474-
uint ret;
475-
fixed (byte *src = &data[0]){
476-
PutBytesBE ((byte *) &ret, src, 4);
412+
Span<byte> data = stackalloc byte[Unsafe.SizeOf<T>()];
413+
T ret = default;
414+
Read(data);
415+
if (BitConverter.IsLittleEndian)
416+
{
417+
data.Reverse();
477418
}
419+
data.CopyTo(new Span<byte>(Unsafe.AsPointer(ref ret), data.Length));
478420
return ret;
479421
}
480-
public unsafe ushort ReadUShort()
481-
{
482-
byte[] data = new byte[4];
483-
Read(data, 0, 4);
484-
485-
uint ret;
486-
fixed (byte *src = &data[0]){
487-
PutBytesBE ((byte *) &ret, src, 4);
488-
}
489-
return (ushort)ret;
490-
}
491422
}
492423

493424
internal class MonoBinaryWriter : BinaryWriter
494425
{
495426
public MonoBinaryWriter(Stream stream) : base(stream) {}
496-
public void WriteString(string val)
497-
{
498-
Write(val.Length);
499-
Write(val.ToCharArray());
500-
}
501-
public void WriteLong(long val)
427+
428+
public override void Write(string val)
502429
{
503-
Write((int)((val >> 32) & 0xffffffff));
504-
Write((int)((val >> 0) & 0xffffffff));
430+
var bytes = Encoding.UTF8.GetBytes(val);
431+
Write(bytes.Length);
432+
Write(bytes);
505433
}
506-
public override void Write(int val)
434+
435+
public override void Write(long val) => WriteBigEndian<long>(val);
436+
public override void Write(int val) => WriteBigEndian<int>(val);
437+
438+
protected unsafe void WriteBigEndian<T>(T val) where T : struct
507439
{
508-
byte[] bytes = BitConverter.GetBytes(val);
509-
Array.Reverse(bytes, 0, bytes.Length);
510-
Write(bytes);
440+
Span<byte> data = stackalloc byte[Unsafe.SizeOf<T>()];
441+
new Span<byte>(Unsafe.AsPointer(ref val), data.Length).CopyTo(data);
442+
if (BitConverter.IsLittleEndian)
443+
{
444+
data.Reverse();
445+
}
446+
base.Write(data);
511447
}
448+
512449
public void WriteObj(DotnetObjectId objectId, MonoSDBHelper SdbHelper)
513450
{
514451
if (objectId.Scheme == "object")
@@ -878,7 +815,7 @@ public async Task<int> CreateString(SessionId sessionId, string value, Cancellat
878815
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdAppDomain>(sessionId, CmdAppDomain.GetRootDomain, commandParams, token);
879816
var root_domain = retDebuggerCmdReader.ReadInt32();
880817
commandParamsWriter.Write(root_domain);
881-
commandParamsWriter.WriteString(value);
818+
commandParamsWriter.Write(value);
882819
retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdAppDomain>(sessionId, CmdAppDomain.CreateString, commandParams, token);
883820
return retDebuggerCmdReader.ReadInt32();
884821
}
@@ -989,7 +926,7 @@ public async Task<int> GetAssemblyId(SessionId sessionId, string asm_name, Cance
989926
{
990927
var commandParams = new MemoryStream();
991928
var commandParamsWriter = new MonoBinaryWriter(commandParams);
992-
commandParamsWriter.WriteString(asm_name);
929+
commandParamsWriter.Write(asm_name);
993930

994931
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdVM>(sessionId, CmdVM.GetAssemblyByName, commandParams, token);
995932
return retDebuggerCmdReader.ReadInt32();
@@ -1124,7 +1061,7 @@ public async Task<int> SetBreakpoint(SessionId sessionId, int methodId, long il_
11241061
commandParamsWriter.Write((byte)1);
11251062
commandParamsWriter.Write((byte)ModifierKind.LocationOnly);
11261063
commandParamsWriter.Write(methodId);
1127-
commandParamsWriter.WriteLong(il_offset);
1064+
commandParamsWriter.Write(il_offset);
11281065
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdEventRequest>(sessionId, CmdEventRequest.Set, commandParams, token);
11291066
return retDebuggerCmdReader.ReadInt32();
11301067
}
@@ -1509,7 +1446,7 @@ public async Task<int> GetMethodIdByName(SessionId sessionId, int type_id, strin
15091446
var commandParams = new MemoryStream();
15101447
var commandParamsWriter = new MonoBinaryWriter(commandParams);
15111448
commandParamsWriter.Write((int)type_id);
1512-
commandParamsWriter.WriteString(method_name);
1449+
commandParamsWriter.Write(method_name);
15131450
commandParamsWriter.Write((int)(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static));
15141451
commandParamsWriter.Write((int)1); //case sensitive
15151452
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdType>(sessionId, CmdType.GetMethodsByNameFlags, commandParams, token);
@@ -1645,7 +1582,7 @@ public async Task<JObject> GetPointerContent(SessionId sessionId, int pointerId,
16451582
var ret = new List<string>();
16461583
var commandParams = new MemoryStream();
16471584
var commandParamsWriter = new MonoBinaryWriter(commandParams);
1648-
commandParamsWriter.WriteLong(pointerValues[pointerId].address);
1585+
commandParamsWriter.Write(pointerValues[pointerId].address);
16491586
commandParamsWriter.Write(pointerValues[pointerId].typeId);
16501587
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdPointer>(sessionId, CmdPointer.GetValue, commandParams, token);
16511588
var varName = pointerValues[pointerId].varName;
@@ -1744,7 +1681,7 @@ public async Task<JObject> CreateJObjectForPtr(SessionId sessionId, ElementType
17441681
{
17451682
string type;
17461683
string value;
1747-
long valueAddress = retDebuggerCmdReader.ReadLong();
1684+
long valueAddress = retDebuggerCmdReader.ReadInt64();
17481685
var typeId = retDebuggerCmdReader.ReadInt32();
17491686
var className = "";
17501687
if (etype == ElementType.FnPtr)
@@ -1955,7 +1892,7 @@ public async Task<JObject> CreateJObjectForVariableValue(SessionId sessionId, Mo
19551892
}
19561893
case ElementType.R4:
19571894
{
1958-
float value = BitConverter.Int32BitsToSingle(retDebuggerCmdReader.ReadInt32());
1895+
float value = retDebuggerCmdReader.ReadSingle();
19591896
ret = CreateJObjectForNumber<float>(value);
19601897
break;
19611898
}
@@ -1967,15 +1904,13 @@ public async Task<JObject> CreateJObjectForVariableValue(SessionId sessionId, Mo
19671904
}
19681905
case ElementType.I8:
19691906
{
1970-
long value = retDebuggerCmdReader.ReadLong();
1907+
long value = retDebuggerCmdReader.ReadInt64();
19711908
ret = CreateJObjectForNumber<long>(value);
19721909
break;
19731910
}
19741911
case ElementType.U8:
19751912
{
1976-
ulong high = (ulong) retDebuggerCmdReader.ReadInt32();
1977-
ulong low = (ulong) retDebuggerCmdReader.ReadInt32();
1978-
var value = ((high << 32) | low);
1913+
ulong value = retDebuggerCmdReader.ReadUInt64();
19791914
ret = CreateJObjectForNumber<ulong>(value);
19801915
break;
19811916
}
@@ -2257,7 +2192,7 @@ public async Task<int> GetTypeByName(SessionId sessionId, string typeToSearch, C
22572192
{
22582193
var commandParams = new MemoryStream();
22592194
var commandParamsWriter = new MonoBinaryWriter(commandParams);
2260-
commandParamsWriter.WriteString(typeToSearch);
2195+
commandParamsWriter.Write(typeToSearch);
22612196
var retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdVM>(sessionId, CmdVM.GetTypes, commandParams, token);
22622197
var count = retDebuggerCmdReader.ReadInt32(); //count ret
22632198
return retDebuggerCmdReader.ReadInt32();

0 commit comments

Comments
 (0)