From 0d259696608e0b593238e23d84b3483454d0028d Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Wed, 17 Nov 2021 20:01:20 -0600 Subject: [PATCH] [wasm][debugger] Tie sdb agent lifetime to the ExecutionContext and simplify the api (#61392) * Make SMonoSdbHelper part of the execution context --- .../debugger/BrowserDebugProxy/DebugStore.cs | 18 +- .../BrowserDebugProxy/DevToolsHelper.cs | 9 + .../MemberReferenceResolver.cs | 81 +- .../debugger/BrowserDebugProxy/MonoProxy.cs | 119 ++- .../BrowserDebugProxy/MonoSDBHelper.cs | 886 +++++++++--------- 5 files changed, 544 insertions(+), 569 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 6ca97d9c4785f..7eb7f7dafe757 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -157,9 +157,9 @@ public VarInfo(Parameter p, MetadataReader pdbReader) public override string ToString() => $"(var-info [{Index}] '{Name}')"; } - internal class NewCliLocation + internal class IlLocation { - public NewCliLocation(MethodInfo method, int offset) + public IlLocation(MethodInfo method, int offset) { Method = method; Offset = offset; @@ -174,7 +174,7 @@ internal class SourceLocation private SourceId id; private int line; private int column; - private NewCliLocation cliLoc; + private IlLocation ilLocation; public SourceLocation(SourceId id, int line, int column) { @@ -188,13 +188,13 @@ public SourceLocation(MethodInfo mi, SequencePoint sp) this.id = mi.SourceId; this.line = sp.StartLine - 1; this.column = sp.StartColumn - 1; - this.cliLoc = new NewCliLocation(mi, sp.Offset); + this.ilLocation = new IlLocation(mi, sp.Offset); } public SourceId Id { get => id; } public int Line { get => line; } public int Column { get => column; } - public NewCliLocation CliLocation => this.cliLoc; + public IlLocation IlLocation => this.ilLocation; public override string ToString() => $"{id}:{Line}:{Column}"; @@ -926,7 +926,7 @@ private class DebugItem public Task Data { get; set; } } - public IEnumerable EnC(SessionId sessionId, AssemblyInfo asm, byte[] meta_data, byte[] pdb_data) + public IEnumerable EnC(AssemblyInfo asm, byte[] meta_data, byte[] pdb_data) { asm.EnC(meta_data, pdb_data); foreach (var method in asm.Methods) @@ -936,12 +936,12 @@ public IEnumerable EnC(SessionId sessionId, AssemblyInfo asm, byte[] } } - public IEnumerable Add(SessionId sessionId, byte[] assembly_data, byte[] pdb_data) + public IEnumerable Add(string name, byte[] assembly_data, byte[] pdb_data) { AssemblyInfo assembly = null; try { - assembly = new AssemblyInfo(sessionId.ToString(), assembly_data, pdb_data); + assembly = new AssemblyInfo(name, assembly_data, pdb_data); } catch (Exception e) { @@ -965,7 +965,7 @@ public IEnumerable Add(SessionId sessionId, byte[] assembly_data, by } } - public async IAsyncEnumerable Load(SessionId sessionId, string[] loaded_files, [EnumeratorCancellation] CancellationToken token) + public async IAsyncEnumerable Load(string[] loaded_files, [EnumeratorCancellation] CancellationToken token) { var asm_files = new List(); var pdb_files = new List(); diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index 97acfe9517d4e..3e7cfd87f010d 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -275,6 +275,13 @@ internal enum PauseOnExceptionsKind internal class ExecutionContext { + public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData) + { + Id = id; + AuxData = auxData; + SdbAgent = sdbAgent; + } + public string DebugId { get; set; } public Dictionary BreakpointRequests { get; } = new Dictionary(); @@ -291,6 +298,7 @@ internal class ExecutionContext public string[] LoadedFiles { get; set; } internal DebugStore store; + internal MonoSDBHelper SdbAgent { get; init; } public TaskCompletionSource Source { get; } = new TaskCompletionSource(); private Dictionary perScopeCaches { get; } = new Dictionary(); @@ -319,6 +327,7 @@ public PerScopeCache GetCacheForScope(int scopeId) public void ClearState() { CallStack = null; + SdbAgent.ClearCache(); perScopeCaches.Clear(); } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index 80b4aa8a977d0..12a4f4f06aa6b 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -18,22 +18,20 @@ internal class MemberReferenceResolver private SessionId sessionId; private int scopeId; private MonoProxy proxy; - private ExecutionContext ctx; + private ExecutionContext context; private PerScopeCache scopeCache; private ILogger logger; private bool localsFetched; private int linqTypeId; - private MonoSDBHelper sdbHelper; public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId sessionId, int scopeId, ILogger logger) { this.sessionId = sessionId; this.scopeId = scopeId; this.proxy = proxy; - this.ctx = ctx; + this.context = ctx; this.logger = logger; scopeCache = ctx.GetCacheForScope(scopeId); - sdbHelper = proxy.SdbHelper; linqTypeId = -1; } @@ -42,11 +40,10 @@ public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId this.sessionId = sessionId; scopeId = -1; this.proxy = proxy; - this.ctx = ctx; + this.context = ctx; this.logger = logger; scopeCache = new PerScopeCache(objectValues); localsFetched = true; - sdbHelper = proxy.SdbHelper; linqTypeId = -1; } @@ -56,7 +53,7 @@ public async Task GetValueFromObject(JToken objRet, CancellationToken t { if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value(), out DotnetObjectId objectId)) { - var exceptionObject = await sdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token); + var exceptionObject = await context.SdbAgent.GetObjectValues(int.Parse(objectId.Value), GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token); var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value().Equals("_message")); exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value() + ": " + exceptionObjectMessage["value"]?["value"]?.Value(); return exceptionObjectMessage["value"]?.Value(); @@ -70,10 +67,9 @@ public async Task GetValueFromObject(JToken objRet, CancellationToken t { if (DotnetObjectId.TryParse(objRet?["get"]?["objectIdValue"]?.Value(), out DotnetObjectId objectId)) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); - commandParamsWriter.WriteObj(objectId, sdbHelper); - var ret = await sdbHelper.InvokeMethod(sessionId, commandParams.ToArray(), objRet["get"]["methodId"].Value(), objRet["name"].Value(), token); + using var commandParamsWriter = new MonoBinaryWriter(); + commandParamsWriter.WriteObj(objectId, context.SdbAgent); + var ret = await context.SdbAgent.InvokeMethod(commandParamsWriter.GetParameterBuffer(), objRet["get"]["methodId"].Value(), objRet["name"].Value(), token); return await GetValueFromObject(ret, token); } @@ -93,32 +89,31 @@ public async Task TryToRunOnLoadedClasses(string varName, CancellationT classNameToFind += part.Trim(); if (typeId != -1) { - var fields = await sdbHelper.GetTypeFields(sessionId, typeId, token); + var fields = await context.SdbAgent.GetTypeFields(typeId, token); foreach (var field in fields) { if (field.Name == part.Trim()) { - var isInitialized = await sdbHelper.TypeIsInitialized(sessionId, typeId, token); + var isInitialized = await context.SdbAgent.TypeIsInitialized(typeId, token); if (isInitialized == 0) { - isInitialized = await sdbHelper.TypeInitialize(sessionId, typeId, token); + isInitialized = await context.SdbAgent.TypeInitialize(typeId, token); } - var valueRet = await sdbHelper.GetFieldValue(sessionId, typeId, field.Id, token); + var valueRet = await context.SdbAgent.GetFieldValue(typeId, field.Id, token); return await GetValueFromObject(valueRet, token); } } - var methodId = await sdbHelper.GetPropertyMethodIdByName(sessionId, typeId, part.Trim(), token); + var methodId = await context.SdbAgent.GetPropertyMethodIdByName(typeId, part.Trim(), token); if (methodId != -1) { - var commandParamsObj = new MemoryStream(); - var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); + using var commandParamsObjWriter = new MonoBinaryWriter(); commandParamsObjWriter.Write(0); //param count - var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); + var retMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, "methodRet", token); return await GetValueFromObject(retMethod, token); } } var store = await proxy.LoadStore(sessionId, token); - var methodInfo = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId)?.Method?.Info; + var methodInfo = context.CallStack.FirstOrDefault(s => s.Id == scopeId)?.Method?.Info; var classNameToFindWithNamespace = string.IsNullOrEmpty(methodInfo?.TypeInfo?.Namespace) ? classNameToFind : @@ -135,7 +130,7 @@ public async Task TryToRunOnLoadedClasses(string varName, CancellationT var type = assembly.GetTypeByName(typeName); if (type == null) return null; - return await sdbHelper.GetTypeIdFromToken(sessionId, assembly.DebugId, type.Token, token); + return await context.SdbAgent.GetTypeIdFromToken(assembly.DebugId, type.Token, token); } async Task TryFindNameInAssembly(List assemblies, string name) @@ -290,18 +285,17 @@ public async Task Resolve(ElementAccessExpressionSyntax elementAccess, switch (objectId.Scheme) { case "array": - rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(objectId.Value), token); + rootObject["value"] = await context.SdbAgent.GetArrayValues(int.Parse(objectId.Value), token); return (JObject)rootObject["value"][elementIdx]["value"]; case "object": - var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); - int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], "ToArray", token); - var commandParamsObj = new MemoryStream(); - var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); - commandParamsObjWriter.WriteObj(objectId, sdbHelper); - var toArrayRetMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, elementAccess.Expression.ToString(), token); + var typeIds = await context.SdbAgent.GetTypeIdFromObject(int.Parse(objectId.Value), true, token); + int methodId = await context.SdbAgent.GetMethodIdByName(typeIds[0], "ToArray", token); + var commandParamsObjWriter = new MonoBinaryWriter(); + commandParamsObjWriter.WriteObj(objectId, context.SdbAgent); + var toArrayRetMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, elementAccess.Expression.ToString(), token); rootObject = await GetValueFromObject(toArrayRetMethod, token); DotnetObjectId.TryParse(rootObject?["objectId"]?.Value(), out DotnetObjectId arrayObjectId); - rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(arrayObjectId.Value), token); + rootObject["value"] = await context.SdbAgent.GetArrayValues(int.Parse(arrayObjectId.Value), token); return (JObject)rootObject["value"][elementIdx]["value"]; default: throw new InvalidOperationException($"Cannot apply indexing with [] to an expression of type '{objectId.Scheme}'"); @@ -340,56 +334,55 @@ public async Task Resolve(InvocationExpressionSyntax method, Dictionary if (rootObject != null) { DotnetObjectId.TryParse(rootObject?["objectId"]?.Value(), out DotnetObjectId objectId); - var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); - int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], methodName, token); - var className = await sdbHelper.GetTypeNameOriginal(sessionId, typeIds[0], token); + var typeIds = await context.SdbAgent.GetTypeIdFromObject(int.Parse(objectId.Value), true, token); + int methodId = await context.SdbAgent.GetMethodIdByName(typeIds[0], methodName, token); + var className = await context.SdbAgent.GetTypeNameOriginal(typeIds[0], token); if (methodId == 0) //try to search on System.Linq.Enumerable { if (linqTypeId == -1) - linqTypeId = await sdbHelper.GetTypeByName(sessionId, "System.Linq.Enumerable", token); - methodId = await sdbHelper.GetMethodIdByName(sessionId, linqTypeId, methodName, token); + linqTypeId = await context.SdbAgent.GetTypeByName("System.Linq.Enumerable", token); + methodId = await context.SdbAgent.GetMethodIdByName(linqTypeId, methodName, token); if (methodId != 0) { foreach (var typeId in typeIds) { - var genericTypeArgs = await sdbHelper.GetTypeParamsOrArgsForGenericType(sessionId, typeId, token); + var genericTypeArgs = await context.SdbAgent.GetTypeParamsOrArgsForGenericType(typeId, token); if (genericTypeArgs.Count > 0) { isTryingLinq = 1; - methodId = await sdbHelper.MakeGenericMethod(sessionId, methodId, genericTypeArgs, token); + methodId = await context.SdbAgent.MakeGenericMethod(methodId, genericTypeArgs, token); break; } } } } if (methodId == 0) { - var typeName = await sdbHelper.GetTypeName(sessionId, typeIds[0], token); + var typeName = await context.SdbAgent.GetTypeName(typeIds[0], token); throw new Exception($"Method '{methodName}' not found in type '{typeName}'"); } - var commandParamsObj = new MemoryStream(); - var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); + using var commandParamsObjWriter = new MonoBinaryWriter(); if (isTryingLinq == 0) - commandParamsObjWriter.WriteObj(objectId, sdbHelper); + commandParamsObjWriter.WriteObj(objectId, context.SdbAgent); if (method.ArgumentList != null) { commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count + isTryingLinq); if (isTryingLinq == 1) - commandParamsObjWriter.WriteObj(objectId, sdbHelper); + commandParamsObjWriter.WriteObj(objectId, context.SdbAgent); foreach (var arg in method.ArgumentList.Arguments) { if (arg.Expression is LiteralExpressionSyntax) { - if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, sdbHelper, token)) + if (!await commandParamsObjWriter.WriteConst(arg.Expression as LiteralExpressionSyntax, context.SdbAgent, token)) return null; } if (arg.Expression is IdentifierNameSyntax) { var argParm = arg.Expression as IdentifierNameSyntax; - if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], sdbHelper, token)) + if (!await commandParamsObjWriter.WriteJsonValue(memberAccessValues[argParm.Identifier.Text], context.SdbAgent, token)) return null; } } - var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); + var retMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, "methodRet", token); return await GetValueFromObject(retMethod, token); } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 7d2dd66ec0812..8b1265d866d4d 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -18,7 +18,6 @@ namespace Microsoft.WebAssembly.Diagnostics { internal class MonoProxy : DevToolsProxy { - internal MonoSDBHelper SdbHelper { get; set; } private IList urlSymbolServerList; private static HttpClient client = new HttpClient(); private HashSet sessions = new HashSet(); @@ -29,7 +28,6 @@ internal class MonoProxy : DevToolsProxy public MonoProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList) : base(loggerFactory) { this.urlSymbolServerList = urlSymbolServerList ?? new List(); - SdbHelper = new MonoSDBHelper(this, logger); } internal ExecutionContext GetContext(SessionId sessionId) @@ -118,7 +116,7 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth bool? is_default = aux_data["isDefault"]?.Value(); if (is_default == true) { - await OnDefaultContext(sessionId, new ExecutionContext { Id = id, AuxData = aux_data }, token); + await OnDefaultContext(sessionId, new ExecutionContext(new MonoSDBHelper (this, logger, sessionId), id, aux_data), token); } } return true; @@ -453,7 +451,7 @@ protected override async Task AcceptCommand(MessageId id, string method, J }; if (context.IsRuntimeReady) - await SdbHelper.EnableExceptions(id, context.PauseOnExceptions, token); + await context.SdbAgent.EnableExceptions(context.PauseOnExceptions, token); // Pass this on to JS too return false; } @@ -540,22 +538,23 @@ protected override async Task AcceptCommand(MessageId id, string method, J } private async Task CallOnFunction(MessageId id, JObject args, CancellationToken token) { + var context = GetContext(id); if (!DotnetObjectId.TryParse(args["objectId"], out DotnetObjectId objectId)) { return false; } switch (objectId.Scheme) { case "object": - args["details"] = await SdbHelper.GetObjectProxy(id, int.Parse(objectId.Value), token); + args["details"] = await context.SdbAgent.GetObjectProxy(int.Parse(objectId.Value), token); break; case "valuetype": - args["details"] = await SdbHelper.GetValueTypeProxy(id, int.Parse(objectId.Value), token); + args["details"] = await context.SdbAgent.GetValueTypeProxy(int.Parse(objectId.Value), token); break; case "pointer": - args["details"] = await SdbHelper.GetPointerContent(id, int.Parse(objectId.Value), token); + args["details"] = await context.SdbAgent.GetPointerContent(int.Parse(objectId.Value), token); break; case "array": - args["details"] = await SdbHelper.GetArrayValuesProxy(id, int.Parse(objectId.Value), token); + args["details"] = await context.SdbAgent.GetArrayValuesProxy(int.Parse(objectId.Value), token); break; case "cfo_res": { @@ -584,10 +583,9 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation if (res.Value?["result"]?["value"]?["type"] == null) //it means that is not a buffer returned from the debugger-agent { byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); - var retDebuggerCmd = new MemoryStream(newBytes); - var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + var retDebuggerCmdReader = new MonoBinaryReader(newBytes); retDebuggerCmdReader.ReadByte(); //number of objects returned. - var obj = await SdbHelper.CreateJObjectForVariableValue(id, retDebuggerCmdReader, "ret", false, -1, false, token); + var obj = await context.SdbAgent.CreateJObjectForVariableValue(retDebuggerCmdReader, "ret", false, -1, false, token); /*JTokenType? res_value_type = res.Value?["result"]?["value"]?.Type;*/ res = Result.OkFromObject(new { result = obj["value"]}); SendResponse(id, res, token); @@ -600,17 +598,17 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation private async Task OnSetVariableValue(MessageId id, int scopeId, string varName, JToken varValue, CancellationToken token) { - ExecutionContext ctx = GetContext(id); - Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId); + ExecutionContext context = GetContext(id); + Frame scope = context.CallStack.FirstOrDefault(s => s.Id == scopeId); if (scope == null) return false; - var varIds = scope.Method.Info.GetLiveVarsAt(scope.Location.CliLocation.Offset); + var varIds = scope.Method.Info.GetLiveVarsAt(scope.Location.IlLocation.Offset); if (varIds == null) return false; var varToSetValue = varIds.FirstOrDefault(v => v.Name == varName); if (varToSetValue == null) return false; - var res = await SdbHelper.SetVariableValue(id, ctx.ThreadId, scopeId, varToSetValue.Index, varValue["value"].Value(), token); + var res = await context.SdbAgent.SetVariableValue(context.ThreadId, scopeId, varToSetValue.Index, varValue["value"].Value(), token); if (res) SendResponse(id, Result.Ok(new JObject()), token); else @@ -620,6 +618,7 @@ private async Task OnSetVariableValue(MessageId id, int scopeId, string va internal async Task RuntimeGetPropertiesInternal(SessionId id, DotnetObjectId objectId, JToken args, CancellationToken token) { + var context = GetContext(id); var accessorPropertiesOnly = false; GetObjectCommandOptions objectValuesOpt = GetObjectCommandOptions.WithProperties; if (args != null) @@ -644,13 +643,13 @@ internal async Task RuntimeGetPropertiesInternal(SessionId id, DotnetObj return res.Value?["result"]; } case "valuetype": - return await SdbHelper.GetValueTypeValues(id, int.Parse(objectId.Value), accessorPropertiesOnly, token); + return await context.SdbAgent.GetValueTypeValues(int.Parse(objectId.Value), accessorPropertiesOnly, token); case "array": - return await SdbHelper.GetArrayValues(id, int.Parse(objectId.Value), token); + return await context.SdbAgent.GetArrayValues(int.Parse(objectId.Value), token); case "object": - return await SdbHelper.GetObjectValues(id, int.Parse(objectId.Value), objectValuesOpt, token); + return await context.SdbAgent.GetObjectValues(int.Parse(objectId.Value), objectValuesOpt, token); case "pointer": - return new JArray{await SdbHelper.GetPointerContent(id, int.Parse(objectId.Value), token)}; + return new JArray{await context.SdbAgent.GetPointerContent(int.Parse(objectId.Value), token)}; case "cfo_res": { Result res = await SendMonoCommand(id, MonoCommands.GetDetails(int.Parse(objectId.Value), args), token); @@ -707,10 +706,10 @@ private async Task ProcessEnC(SessionId sessionId, ExecutionContext contex int pdb_size = retDebuggerCmdReader.ReadInt32(); byte[] pdb_buf = retDebuggerCmdReader.ReadBytes(pdb_size); - var assemblyName = await SdbHelper.GetAssemblyNameFromModule(sessionId, moduleId, token); + var assemblyName = await context.SdbAgent.GetAssemblyNameFromModule(moduleId, token); DebugStore store = await LoadStore(sessionId, token); AssemblyInfo asm = store.GetAssemblyByName(assemblyName); - foreach (var method in store.EnC(sessionId, asm, meta_buf, pdb_buf)) + foreach (var method in store.EnC(asm, meta_buf, pdb_buf)) await ResetBreakpoint(sessionId, method, token); return true; } @@ -718,7 +717,7 @@ private async Task ProcessEnC(SessionId sessionId, ExecutionContext contex private async Task SendBreakpointsOfMethodUpdated(SessionId sessionId, ExecutionContext context, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { var methodId = retDebuggerCmdReader.ReadInt32(); - var method = await SdbHelper.GetMethodInfo(sessionId, methodId, token); + var method = await context.SdbAgent.GetMethodInfo(methodId, token); if (method == null) { return true; @@ -737,12 +736,11 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con { var callFrames = new List(); var frames = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(thread_id); commandParamsWriter.Write(0); commandParamsWriter.Write(-1); - var retDebuggerCmdReader = await SdbHelper.SendDebuggerAgentCommand(sessionId, CmdThread.GetFrameInfo, commandParams, token); + using var retDebuggerCmdReader = await context.SdbAgent.SendDebuggerAgentCommand(CmdThread.GetFrameInfo, commandParamsWriter, token); var frame_count = retDebuggerCmdReader.ReadInt32(); //Console.WriteLine("frame_count - " + frame_count); for (int j = 0; j < frame_count; j++) { @@ -751,7 +749,7 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con var il_pos = retDebuggerCmdReader.ReadInt32(); var flags = retDebuggerCmdReader.ReadByte(); DebugStore store = await LoadStore(sessionId, token); - var method = await SdbHelper.GetMethodInfo(sessionId, methodId, token); + var method = await context.SdbAgent.GetMethodInfo(methodId, token); SourceLocation location = method?.Info.GetLocationByIl(il_pos); @@ -839,8 +837,7 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec ExecutionContext context = GetContext(sessionId); byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); - var retDebuggerCmd = new MemoryStream(newBytes); - var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + using var retDebuggerCmdReader = new MonoBinaryReader(newBytes); retDebuggerCmdReader.ReadBytes(11); //skip HEADER_LEN retDebuggerCmdReader.ReadByte(); //suspend_policy var number_of_events = retDebuggerCmdReader.ReadInt32(); //number of events -> should be always one @@ -848,7 +845,7 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec var event_kind = (EventKind)retDebuggerCmdReader.ReadByte(); //event kind var request_id = retDebuggerCmdReader.ReadInt32(); //request id if (event_kind == EventKind.Step) - await SdbHelper.ClearSingleStep(sessionId, request_id, token); + await context.SdbAgent.ClearSingleStep(request_id, token); int thread_id = retDebuggerCmdReader.ReadInt32(); switch (event_kind) { @@ -869,13 +866,13 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec string reason = "exception"; int object_id = retDebuggerCmdReader.ReadInt32(); var caught = retDebuggerCmdReader.ReadByte(); - var exceptionObject = await SdbHelper.GetObjectValues(sessionId, object_id, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token); + var exceptionObject = await context.SdbAgent.GetObjectValues(object_id, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token); var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value().Equals("_message")); var data = JObject.FromObject(new { type = "object", subtype = "error", - className = await SdbHelper.GetClassNameFromObject(sessionId, object_id, token), + className = await context.SdbAgent.GetClassNameFromObject(object_id, token), uncaught = caught == 0, description = exceptionObjectMessage["value"]["value"].Value(), objectId = $"dotnet:object:{object_id}" @@ -977,32 +974,30 @@ private async Task OnResume(MessageId msg_id, CancellationToken token) } //discard managed frames - SdbHelper.ClearCache(); GetContext(msg_id).ClearState(); } - private async Task Step(MessageId msg_id, StepKind kind, CancellationToken token) + private async Task Step(MessageId msgId, StepKind kind, CancellationToken token) { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = GetContext(msgId); if (context.CallStack == null) return false; if (context.CallStack.Count <= 1 && kind == StepKind.Out) return false; - var step = await SdbHelper.Step(msg_id, context.ThreadId, kind, token); + var step = await context.SdbAgent.Step(context.ThreadId, kind, token); if (step == false) { - SdbHelper.ClearCache(); context.ClearState(); - await SendCommand(msg_id, "Debugger.stepOut", new JObject(), token); + await SendCommand(msgId, "Debugger.stepOut", new JObject(), token); return false; } - SendResponse(msg_id, Result.Ok(new JObject()), token); + SendResponse(msgId, Result.Ok(new JObject()), token); context.ClearState(); - await SendCommand(msg_id, "Debugger.resume", new JObject(), token); + await SendCommand(msgId, "Debugger.resume", new JObject(), token); return true; } @@ -1055,7 +1050,7 @@ private async Task OnAssemblyLoadedJSEvent(SessionId sessionId, JObject ev var pdb_data = string.IsNullOrEmpty(pdb_b64) ? null : Convert.FromBase64String(pdb_b64); var context = GetContext(sessionId); - foreach (var source in store.Add(sessionId, assembly_data, pdb_data)) + foreach (var source in store.Add(assembly_name, assembly_data, pdb_data)) { await OnSourceFileAdded(sessionId, source, context, token); } @@ -1114,20 +1109,20 @@ internal async Task GetScopeProperties(SessionId msg_id, int scopeId, Ca { try { - ExecutionContext ctx = GetContext(msg_id); - Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId); + ExecutionContext context = GetContext(msg_id); + Frame scope = context.CallStack.FirstOrDefault(s => s.Id == scopeId); if (scope == null) return Result.Err(JObject.FromObject(new { message = $"Could not find scope with id #{scopeId}" })); - VarInfo[] varIds = scope.Method.Info.GetLiveVarsAt(scope.Location.CliLocation.Offset); + VarInfo[] varIds = scope.Method.Info.GetLiveVarsAt(scope.Location.IlLocation.Offset); - var values = await SdbHelper.StackFrameGetValues(msg_id, scope.Method, ctx.ThreadId, scopeId, varIds, token); + var values = await context.SdbAgent.StackFrameGetValues(scope.Method, context.ThreadId, scopeId, varIds, token); if (values != null) { if (values == null || values.Count == 0) return Result.OkFromObject(new { result = Array.Empty() }); - PerScopeCache frameCache = ctx.GetCacheForScope(scopeId); + PerScopeCache frameCache = context.GetCacheForScope(scopeId); foreach (JObject value in values) { frameCache.Locals[value["name"]?.Value()] = value; @@ -1145,14 +1140,15 @@ internal async Task GetScopeProperties(SessionId msg_id, int scopeId, Ca private async Task SetMonoBreakpoint(SessionId sessionId, string reqId, SourceLocation location, string condition, CancellationToken token) { + var context = GetContext(sessionId); var bp = new Breakpoint(reqId, location, condition, BreakpointState.Pending); - string asm_name = bp.Location.CliLocation.Method.Assembly.Name; - int method_token = bp.Location.CliLocation.Method.Token; - int il_offset = bp.Location.CliLocation.Offset; + string asm_name = bp.Location.IlLocation.Method.Assembly.Name; + int method_token = bp.Location.IlLocation.Method.Token; + int il_offset = bp.Location.IlLocation.Offset; - var assembly_id = await SdbHelper.GetAssemblyId(sessionId, asm_name, token); - var methodId = await SdbHelper.GetMethodIdByToken(sessionId, assembly_id, method_token, token); - var breakpoint_id = await SdbHelper.SetBreakpoint(sessionId, methodId, il_offset, token); + var assembly_id = await context.SdbAgent.GetAssemblyId(asm_name, token); + var methodId = await context.SdbAgent.GetMethodIdByToken(assembly_id, method_token, token); + var breakpoint_id = await context.SdbAgent.SetBreakpoint(methodId, il_offset, token); if (breakpoint_id > 0) { @@ -1196,7 +1192,7 @@ internal async Task LoadStore(SessionId sessionId, CancellationToken } await - foreach (SourceFile source in context.store.Load(sessionId, loaded_files, token).WithCancellation(token)) + foreach (SourceFile source in context.store.Load(loaded_files, token).WithCancellation(token)) { await OnSourceFileAdded(sessionId, source, context, token); } @@ -1217,21 +1213,20 @@ private async Task RuntimeReady(SessionId sessionId, CancellationTok if (Interlocked.CompareExchange(ref context.ready, new TaskCompletionSource(), null) != null) return await context.ready.Task; - var commandParams = new MemoryStream(); - await SdbHelper.SendDebuggerAgentCommand(sessionId, CmdEventRequest.ClearAllBreakpoints, commandParams, token); + await context.SdbAgent.SendDebuggerAgentCommand(CmdEventRequest.ClearAllBreakpoints, null, token); if (context.PauseOnExceptions != PauseOnExceptionsKind.None && context.PauseOnExceptions != PauseOnExceptionsKind.Unset) - await SdbHelper.EnableExceptions(sessionId, context.PauseOnExceptions, token); + await context.SdbAgent.EnableExceptions(context.PauseOnExceptions, token); - await SdbHelper.SetProtocolVersion(sessionId, token); - await SdbHelper.EnableReceiveRequests(sessionId, EventKind.UserBreak, token); - await SdbHelper.EnableReceiveRequests(sessionId, EventKind.EnC, token); - await SdbHelper.EnableReceiveRequests(sessionId, EventKind.MethodUpdate, token); + await context.SdbAgent.SetProtocolVersion(token); + await context.SdbAgent.EnableReceiveRequests(EventKind.UserBreak, token); + await context.SdbAgent.EnableReceiveRequests(EventKind.EnC, token); + await context.SdbAgent.EnableReceiveRequests(EventKind.MethodUpdate, token); DebugStore store = await LoadStore(sessionId, token); context.ready.SetResult(store); SendEvent(sessionId, "Mono.runtimeReady", new JObject(), token); - SdbHelper.ResetStore(store); + context.SdbAgent.ResetStore(store); return store; } @@ -1259,7 +1254,7 @@ private async Task RemoveBreakpoint(SessionId msg_id, JObject args, bool isEnCRe foreach (Breakpoint bp in breakpointRequest.Locations) { - var breakpoint_removed = await SdbHelper.RemoveBreakpoint(msg_id, bp.RemoteId, token); + var breakpoint_removed = await context.SdbAgent.RemoveBreakpoint(bp.RemoteId, token); if (breakpoint_removed) { bp.RemoteId = -1; @@ -1300,7 +1295,7 @@ private async Task SetBreakpoint(SessionId sessionId, DebugStore store, Breakpoi foreach (IGrouping sourceId in locations) { SourceLocation loc = sourceId.First(); - req.Method = loc.CliLocation.Method; + req.Method = loc.IlLocation.Method; if (req.Method.IsHiddenFromDebugger) continue; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 86169af26b5cb..4ad3f6a45cb71 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -424,11 +424,23 @@ public TypeInfoWithDebugInformation(TypeInfo typeInfo, int debugId, string name) internal class MonoBinaryReader : BinaryReader { public bool HasError { get; } - public MonoBinaryReader(Stream stream, bool hasError = false) : base(stream) + + private MonoBinaryReader(Stream stream, bool hasError = false) : base(stream) { HasError = hasError; } + public MonoBinaryReader(byte [] data) : base(new MemoryStream(data)) {} + + public static MonoBinaryReader From(Result result) + { + byte[] newBytes = Array.Empty(); + if (!result.IsErr) { + newBytes = Convert.FromBase64String(result.Value?["result"]?["value"]?["value"]?.Value()); + } + return new MonoBinaryReader(new MemoryStream(newBytes), result.IsErr); + } + public override string ReadString() { var valueLen = ReadInt32(); @@ -442,8 +454,9 @@ public override string ReadString() public override sbyte ReadSByte() => (sbyte)ReadInt32(); public byte ReadUByte() => (byte)ReadUInt32(); public ushort ReadUShort() => (ushort)ReadUInt32(); - public override int ReadInt32() => ReadBigEndian(); + // Big endian overrides + public override int ReadInt32() => ReadBigEndian(); public override double ReadDouble() => ReadBigEndian(); public override uint ReadUInt32() => ReadBigEndian(); public override float ReadSingle() => ReadBigEndian(); @@ -466,7 +479,7 @@ protected unsafe T ReadBigEndian() where T : struct internal class MonoBinaryWriter : BinaryWriter { - public MonoBinaryWriter(Stream stream) : base(stream) {} + public MonoBinaryWriter() : base(new MemoryStream(20)) {} public override void Write(string val) { @@ -489,45 +502,85 @@ protected unsafe void WriteBigEndian(T val) where T : struct base.Write(data); } + private void Write(ElementType type, T value) where T : struct => Write((byte)type, value); + + private void Write(T1 type, T2 value) where T1 : struct where T2 : struct + { + WriteBigEndian(type); + WriteBigEndian(value); + } + public void WriteObj(DotnetObjectId objectId, MonoSDBHelper SdbHelper) { if (objectId.Scheme == "object") { - Write((byte)ElementType.Class); - Write(int.Parse(objectId.Value)); + Write(ElementType.Class, int.Parse(objectId.Value)); } - if (objectId.Scheme == "valuetype") + else if (objectId.Scheme == "valuetype") { Write(SdbHelper.valueTypes[int.Parse(objectId.Value)].valueTypeBuffer); } } - public async Task WriteConst(SessionId sessionId, LiteralExpressionSyntax constValue, MonoSDBHelper SdbHelper, CancellationToken token) + public async Task WriteConst(LiteralExpressionSyntax constValue, MonoSDBHelper SdbHelper, CancellationToken token) { switch (constValue.Kind()) { case SyntaxKind.NumericLiteralExpression: { - Write((byte)ElementType.I4); - Write((int)constValue.Token.Value); + switch (constValue.Token.Value) { + case double d: + Write(ElementType.R8, d); + break; + case float f: + Write(ElementType.R4, f); + break; + case long l: + Write(ElementType.I8, l); + break; + case ulong ul: + Write(ElementType.U8, ul); + break; + case byte b: + Write(ElementType.U1, (int)b); + break; + case sbyte sb: + Write(ElementType.I1, (uint)sb); + break; + case ushort us: + Write(ElementType.U2, (int)us); + break; + case short s: + Write(ElementType.I2, (uint)s); + break; + case uint ui: + Write(ElementType.U4, ui); + break; + case IntPtr ip: + Write(ElementType.I, (int)ip); + break; + case UIntPtr up: + Write(ElementType.U, (uint)up); + break; + default: + Write(ElementType.I4, (int)constValue.Token.Value); + break; + } return true; } case SyntaxKind.StringLiteralExpression: { - int stringId = await SdbHelper.CreateString(sessionId, (string)constValue.Token.Value, token); - Write((byte)ElementType.String); - Write((int)stringId); + int stringId = await SdbHelper.CreateString((string)constValue.Token.Value, token); + Write(ElementType.String, stringId); return true; } case SyntaxKind.TrueLiteralExpression: { - Write((byte)ElementType.Boolean); - Write((int)1); + Write(ElementType.Boolean, 1); return true; } case SyntaxKind.FalseLiteralExpression: { - Write((byte)ElementType.Boolean); - Write((int)0); + Write(ElementType.Boolean, 0); return true; } case SyntaxKind.NullLiteralExpression: @@ -539,38 +592,31 @@ public async Task WriteConst(SessionId sessionId, LiteralExpressionSyntax } case SyntaxKind.CharacterLiteralExpression: { - Write((byte)ElementType.Char); - Write((int)(char)constValue.Token.Value); + Write(ElementType.Char, (int)(char)constValue.Token.Value); return true; } } return false; } - public async Task WriteJsonValue(SessionId sessionId, JObject objValue, MonoSDBHelper SdbHelper, CancellationToken token) + public async Task WriteJsonValue(JObject objValue, MonoSDBHelper SdbHelper, CancellationToken token) { switch (objValue["type"].Value()) { case "number": { - Write((byte)ElementType.I4); - Write(objValue["value"].Value()); + Write(ElementType.I4, objValue["value"].Value()); return true; } case "string": { - int stringId = await SdbHelper.CreateString(sessionId, objValue["value"].Value(), token); - Write((byte)ElementType.String); - Write((int)stringId); + int stringId = await SdbHelper.CreateString(objValue["value"].Value(), token); + Write(ElementType.String, stringId); return true; } case "boolean": { - Write((byte)ElementType.Boolean); - if (objValue["value"].Value()) - Write((int)1); - else - Write((int)0); + Write(ElementType.Boolean, objValue["value"].Value() ? 1 : 0); return true; } case "object": @@ -582,6 +628,17 @@ public async Task WriteJsonValue(SessionId sessionId, JObject objValue, Mo } return false; } + + public ArraySegment GetParameterBuffer() + { + ((MemoryStream)BaseStream).TryGetBuffer(out var segment); + return segment; + } + + public (string data, int length) ToBase64() { + var segment = GetParameterBuffer(); + return (Convert.ToBase64String(segment), segment.Count); + } } internal class FieldTypeClass { @@ -649,14 +706,16 @@ internal class MonoSDBHelper private MonoProxy proxy; private DebugStore store; + private SessionId sessionId; private readonly ILogger logger; private Regex regexForAsyncLocals = new Regex(@"\<([^)]*)\>", RegexOptions.Singleline); - public MonoSDBHelper(MonoProxy proxy, ILogger logger) + public MonoSDBHelper(MonoProxy proxy, ILogger logger, SessionId sessionId) { this.proxy = proxy; this.logger = logger; + this.sessionId = sessionId; ResetStore(null); } @@ -669,20 +728,20 @@ public void ResetStore(DebugStore store) ClearCache(); } - public async Task GetAssemblyInfo(SessionId sessionId, int assemblyId, CancellationToken token) + public async Task GetAssemblyInfo(int assemblyId, CancellationToken token) { AssemblyInfo asm = null; if (assemblies.TryGetValue(assemblyId, out asm)) { return asm; } - var assemblyName = await GetAssemblyName(sessionId, assemblyId, token); + var assemblyName = await GetAssemblyName(assemblyId, token); asm = store.GetAssemblyByName(assemblyName); if (asm == null) { - assemblyName = await GetAssemblyFileNameFromId(sessionId, assemblyId, token); //maybe is a lazy loaded assembly + assemblyName = await GetAssemblyFileNameFromId(assemblyId, token); //maybe is a lazy loaded assembly asm = store.GetAssemblyByName(assemblyName); if (asm == null) { @@ -695,17 +754,17 @@ public async Task GetAssemblyInfo(SessionId sessionId, int assembl return asm; } - public async Task GetMethodInfo(SessionId sessionId, int methodId, CancellationToken token) + public async Task GetMethodInfo(int methodId, CancellationToken token) { MethodInfoWithDebugInformation methodDebugInfo = null; if (methods.TryGetValue(methodId, out methodDebugInfo)) { return methodDebugInfo; } - var methodToken = await GetMethodToken(sessionId, methodId, token); - var assemblyId = await GetAssemblyIdFromMethod(sessionId, methodId, token); + var methodToken = await GetMethodToken(methodId, token); + var assemblyId = await GetAssemblyIdFromMethod(methodId, token); - var asm = await GetAssemblyInfo(sessionId, assemblyId, token); + var asm = await GetAssemblyInfo(assemblyId, token); if (asm == null) { @@ -734,12 +793,12 @@ public async Task GetMethodInfo(SessionId sessio return null; } - string methodName = await GetMethodName(sessionId, methodId, token); + string methodName = await GetMethodName(methodId, token); methods[methodId] = new MethodInfoWithDebugInformation(method, methodId, methodName); return methods[methodId]; } - public async Task GetTypeInfo(SessionId sessionId, int typeId, CancellationToken token) + public async Task GetTypeInfo(int typeId, CancellationToken token) { TypeInfoWithDebugInformation typeDebugInfo = null; if (types.TryGetValue(typeId, out typeDebugInfo)) @@ -749,10 +808,10 @@ public async Task GetTypeInfo(SessionId sessionId, TypeInfo type = null; - var typeToken = await GetTypeToken(sessionId, typeId, token); - var typeName = await GetTypeName(sessionId, typeId, token); - var assemblyId = await GetAssemblyFromType(sessionId, typeId, token); - var asm = await GetAssemblyInfo(sessionId, assemblyId, token); + var typeToken = await GetTypeToken(typeId, token); + var typeName = await GetTypeName(typeId, token); + var assemblyId = await GetAssemblyFromType(typeId, token); + var asm = await GetAssemblyInfo(assemblyId, token); if (asm == null) { @@ -778,40 +837,29 @@ public void ClearCache() pointerValues = new Dictionary(); } - public async Task SetProtocolVersion(SessionId sessionId, CancellationToken token) + public async Task SetProtocolVersion(CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(MAJOR_VERSION); commandParamsWriter.Write(MINOR_VERSION); commandParamsWriter.Write((byte)0); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.SetProtocolVersion, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdVM.SetProtocolVersion, commandParamsWriter, token); return true; } - public async Task EnableReceiveRequests(SessionId sessionId, EventKind eventKind, CancellationToken token) + public async Task EnableReceiveRequests(EventKind eventKind, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((byte)eventKind); commandParamsWriter.Write((byte)SuspendPolicy.None); commandParamsWriter.Write((byte)0); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Set, commandParamsWriter, token); return true; } - internal async Task SendDebuggerAgentCommandInternal(SessionId sessionId, int command_set, int command, MemoryStream parms, CancellationToken token) - { - Result res = await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommand(GetId(), command_set, command, Convert.ToBase64String(parms.ToArray())), token); - byte[] newBytes = Array.Empty(); - if (!res.IsErr) { - newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); - } - var retDebuggerCmd = new MemoryStream(newBytes); - var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd, res.IsErr); - return retDebuggerCmdReader; - } + internal async Task SendDebuggerAgentCommand(T command, MonoBinaryWriter arguments, CancellationToken token) => + MonoBinaryReader.From (await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommand(GetId(), (int)GetCommandSetForCommand(command), (int)(object)command, arguments?.ToBase64().data ?? string.Empty), token)); internal CommandSet GetCommandSetForCommand(T command) => command switch { @@ -833,99 +881,78 @@ internal CommandSet GetCommandSetForCommand(T command) => _ => throw new Exception ("Unknown CommandSet") }; - internal Task SendDebuggerAgentCommand(SessionId sessionId, T command, MemoryStream parms, CancellationToken token) where T : Enum => - SendDebuggerAgentCommandInternal(sessionId, (int)GetCommandSetForCommand(command), (int)(object)command, parms, token); - - internal Task SendDebuggerAgentCommandWithParms(SessionId sessionId, T command, MemoryStream parms, int type, string extraParm, CancellationToken token) where T : Enum => - SendDebuggerAgentCommandWithParmsInternal(sessionId, (int)GetCommandSetForCommand(command), (int)(object)command, parms, type, extraParm, token); + internal async Task SendDebuggerAgentCommandWithParms(T command, (string data, int length) encoded, int type, string extraParm, CancellationToken token) => + MonoBinaryReader.From(await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommandWithParms(GetId(), (int)GetCommandSetForCommand(command), (int)(object)command, encoded.data, encoded.length, type, extraParm), token)); - internal async Task SendDebuggerAgentCommandWithParmsInternal(SessionId sessionId, int command_set, int command, MemoryStream parms, int type, string extraParm, CancellationToken token) + public async Task CreateString(string value, CancellationToken token) { - Result res = await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommandWithParms(GetId(), command_set, command, Convert.ToBase64String(parms.ToArray()), parms.ToArray().Length, type, extraParm), token); - byte[] newBytes = Array.Empty(); - if (!res.IsErr) { - newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); - } - var retDebuggerCmd = new MemoryStream(newBytes); - var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd, res.IsErr); - return retDebuggerCmdReader; - } - - public async Task CreateString(SessionId sessionId, string value, CancellationToken token) - { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAppDomain.GetRootDomain, commandParams, token); - var root_domain = retDebuggerCmdReader.ReadInt32(); - commandParamsWriter.Write(root_domain); + using var commandParamsWriter = new MonoBinaryWriter(); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAppDomain.GetRootDomain, commandParamsWriter, token); + var root = retDebuggerCmdReader.ReadInt32(); + commandParamsWriter.Write(root); commandParamsWriter.Write(value); - retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAppDomain.CreateString, commandParams, token); - return retDebuggerCmdReader.ReadInt32(); + using var stringDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAppDomain.CreateString, commandParamsWriter, token); + return stringDebuggerCmdReader.ReadInt32(); } - public async Task GetMethodToken(SessionId sessionId, int methodId, CancellationToken token) + public async Task GetMethodToken(int methodId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.Token, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.Token, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32() & 0xffffff; //token } - public async Task MakeGenericMethod(SessionId sessionId, int methodId, List genericTypes, CancellationToken token) + public async Task MakeGenericMethod(int methodId, List genericTypes, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); commandParamsWriter.Write(genericTypes.Count); foreach (var genericType in genericTypes) { commandParamsWriter.Write(genericType); } - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.MakeGenericMethod, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.MakeGenericMethod, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task GetMethodIdByToken(SessionId sessionId, int assembly_id, int method_token, CancellationToken token) + public async Task GetMethodIdByToken(int assembly_id, int method_token, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(assembly_id); commandParamsWriter.Write(method_token | (int)TokenType.MdtMethodDef); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetMethodFromToken, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAssembly.GetMethodFromToken, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task GetAssemblyIdFromType(SessionId sessionId, int type_id, CancellationToken token) + public async Task GetAssemblyIdFromType(int type_id, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(type_id); commandParamsWriter.Write((int) MonoTypeNameFormat.FormatReflection); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadString(); //namespace retDebuggerCmdReader.ReadString(); //name retDebuggerCmdReader.ReadString(); //formatted name return retDebuggerCmdReader.ReadInt32(); } - public async Task> GetTypeParamsOrArgsForGenericType(SessionId sessionId, int typeId, CancellationToken token) + public async Task> GetTypeParamsOrArgsForGenericType(int typeId, CancellationToken token) { - var typeInfo = await GetTypeInfo(sessionId, typeId, token); + var typeInfo = await GetTypeInfo(typeId, token); - if (typeInfo == null) + if (typeInfo is null) return null; if (typeInfo.TypeParamsOrArgsForGenericType != null) return typeInfo.TypeParamsOrArgsForGenericType; var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); commandParamsWriter.Write((int) MonoTypeNameFormat.FormatReflection); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadString(); //namespace retDebuggerCmdReader.ReadString(); //name @@ -955,129 +982,118 @@ public async Task> GetTypeParamsOrArgsForGenericType(SessionId session return ret; } - public async Task GetAssemblyIdFromMethod(SessionId sessionId, int methodId, CancellationToken token) + public async Task GetAssemblyIdFromMethod(int methodId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.Assembly, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.Assembly, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); //assembly_id } - public async Task GetAssemblyId(SessionId sessionId, string asm_name, CancellationToken token) + public async Task GetAssemblyId(string asm_name, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(asm_name); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.GetAssemblyByName, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdVM.GetAssemblyByName, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task GetAssemblyNameFromModule(SessionId sessionId, int moduleId, CancellationToken token) + public async Task GetAssemblyNameFromModule(int moduleId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); + using var command_params_writer = new MonoBinaryWriter(); command_params_writer.Write(moduleId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdModule.GetInfo, command_params, token); + using var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(CmdModule.GetInfo, command_params_writer, token); ret_debugger_cmd_reader.ReadString(); return ret_debugger_cmd_reader.ReadString(); } - public async Task GetAssemblyName(SessionId sessionId, int assembly_id, CancellationToken token) + public async Task GetAssemblyName(int assembly_id, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(assembly_id); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetLocation, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAssembly.GetLocation, commandParamsWriter, token); return retDebuggerCmdReader.ReadString(); } - public async Task GetFullAssemblyName(SessionId sessionId, int assemblyId, CancellationToken token) + public async Task GetFullAssemblyName(int assemblyId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(assemblyId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetName, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAssembly.GetName, commandParamsWriter, token); var name = retDebuggerCmdReader.ReadString(); return name; } - public async Task GetAssemblyFileNameFromId(SessionId sessionId, int assemblyId, CancellationToken token) + public async Task GetAssemblyFileNameFromId(int assemblyId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(assemblyId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetName, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAssembly.GetName, commandParamsWriter, token); var name = retDebuggerCmdReader.ReadString(); return name.Remove(name.IndexOf(",")) + ".dll"; } - public async Task GetMethodName(SessionId sessionId, int methodId, CancellationToken token) + public async Task GetMethodName(int methodId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetNameFull, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.GetNameFull, commandParamsWriter, token); var methodName = retDebuggerCmdReader.ReadString(); return methodName.Substring(methodName.IndexOf(":")+1); } - public async Task MethodIsStatic(SessionId sessionId, int methodId, CancellationToken token) + public async Task MethodIsStatic(int methodId, CancellationToken token) { - var methodInfo = await GetMethodInfo(sessionId, methodId, token); + var methodInfo = await GetMethodInfo(methodId, token); if (methodInfo != null) return methodInfo.Info.IsStatic(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.GetInfo, commandParamsWriter, token); var flags = retDebuggerCmdReader.ReadInt32(); return (flags & 0x0010) > 0; //check method is static } - public async Task GetParamCount(SessionId sessionId, int methodId, CancellationToken token) + public async Task GetParamCount(int methodId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.GetParamInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadInt32(); int param_count = retDebuggerCmdReader.ReadInt32(); return param_count; } - public async Task GetReturnType(SessionId sessionId, int methodId, CancellationToken token) + public async Task GetReturnType(int methodId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.GetParamInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadInt32(); retDebuggerCmdReader.ReadInt32(); retDebuggerCmdReader.ReadInt32(); var retType = retDebuggerCmdReader.ReadInt32(); - var ret = await GetTypeName(sessionId, retType, token); + var ret = await GetTypeName(retType, token); return ret; } - public async Task GetParameters(SessionId sessionId, int methodId, CancellationToken token) + public async Task GetParameters(int methodId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.GetParamInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadInt32(); var paramCount = retDebuggerCmdReader.ReadInt32(); retDebuggerCmdReader.ReadInt32(); @@ -1086,7 +1102,7 @@ public async Task GetParameters(SessionId sessionId, int methodId, Cance for (int i = 0 ; i < paramCount; i++) { var paramType = retDebuggerCmdReader.ReadInt32(); - parameters += await GetTypeName(sessionId, paramType, token); + parameters += await GetTypeName(paramType, token); parameters = parameters.Replace("System.Func", "Func"); if (i + 1 < paramCount) parameters += ","; @@ -1095,38 +1111,35 @@ public async Task GetParameters(SessionId sessionId, int methodId, Cance return parameters; } - public async Task SetBreakpoint(SessionId sessionId, int methodId, long il_offset, CancellationToken token) + public async Task SetBreakpoint(int methodId, long il_offset, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((byte)EventKind.Breakpoint); commandParamsWriter.Write((byte)SuspendPolicy.None); commandParamsWriter.Write((byte)1); commandParamsWriter.Write((byte)ModifierKind.LocationOnly); commandParamsWriter.Write(methodId); commandParamsWriter.Write(il_offset); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Set, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task RemoveBreakpoint(SessionId sessionId, int breakpoint_id, CancellationToken token) + public async Task RemoveBreakpoint(int breakpoint_id, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((byte)EventKind.Breakpoint); commandParamsWriter.Write((int) breakpoint_id); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Clear, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Clear, commandParamsWriter, token); if (retDebuggerCmdReader != null) return true; return false; } - public async Task Step(SessionId sessionId, int thread_id, StepKind kind, CancellationToken token) + public async Task Step(int thread_id, StepKind kind, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((byte)EventKind.Step); commandParamsWriter.Write((byte)SuspendPolicy.None); commandParamsWriter.Write((byte)1); @@ -1135,8 +1148,8 @@ public async Task Step(SessionId sessionId, int thread_id, StepKind kind, commandParamsWriter.Write((int)StepSize.Line); commandParamsWriter.Write((int)kind); commandParamsWriter.Write((int)(StepFilter.StaticCtor | StepFilter.DebuggerHidden)); //filter - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); - if (retDebuggerCmdReader == null) + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Set, commandParamsWriter, token); + if (retDebuggerCmdReader.HasError) return false; var isBPOnManagedCode = retDebuggerCmdReader.ReadInt32(); if (isBPOnManagedCode == 0) @@ -1144,93 +1157,79 @@ public async Task Step(SessionId sessionId, int thread_id, StepKind kind, return true; } - public async Task ClearSingleStep(SessionId sessionId, int req_id, CancellationToken token) + public async Task ClearSingleStep(int req_id, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((byte)EventKind.Step); commandParamsWriter.Write((int) req_id); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Clear, commandParams, token); - - if (retDebuggerCmdReader != null) - return true; - return false; + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Clear, commandParamsWriter, token); + return !retDebuggerCmdReader.HasError ? true : false; } - public async Task GetFieldValue(SessionId sessionId, int typeId, int fieldId, CancellationToken token) + public async Task GetFieldValue(int typeId, int fieldId, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); commandParamsWriter.Write(1); commandParamsWriter.Write(fieldId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetValues, commandParams, token); - return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "", false, -1, false, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetValues, commandParamsWriter, token); + return await CreateJObjectForVariableValue(retDebuggerCmdReader, "", false, -1, false, token); } - public async Task TypeIsInitialized(SessionId sessionId, int typeId, CancellationToken token) + public async Task TypeIsInitialized(int typeId, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.IsInitialized, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.IsInitialized, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task TypeInitialize(SessionId sessionId, int typeId, CancellationToken token) + public async Task TypeInitialize(int typeId, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.Initialize, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.Initialize, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task GetTypePropertiesReader(SessionId sessionId, int typeId, CancellationToken token) + public async Task GetTypePropertiesReader(int typeId, CancellationToken token) { - var typeInfo = await GetTypeInfo(sessionId, typeId, token); + var typeInfo = await GetTypeInfo(typeId, token); - if (typeInfo == null) + if (typeInfo is null) return null; - if (typeInfo.PropertiesBuffer != null) - { - var retDebuggerCmd = new MemoryStream(typeInfo.PropertiesBuffer); - var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); - return retDebuggerCmdReader; - } + if (typeInfo.PropertiesBuffer is not null) + return new MonoBinaryReader(typeInfo.PropertiesBuffer); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); - var reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); - typeInfo.PropertiesBuffer = reader.ReadBytes((int)reader.BaseStream.Length); - reader.BaseStream.Position = 0; + var reader = await SendDebuggerAgentCommand(CmdType.GetProperties, commandParamsWriter, token); + typeInfo.PropertiesBuffer = ((MemoryStream)reader.BaseStream).ToArray(); return reader; } - public async Task> GetTypeFields(SessionId sessionId, int typeId, CancellationToken token) + public async Task> GetTypeFields(int typeId, CancellationToken token) { - var typeInfo = await GetTypeInfo(sessionId, typeId, token); + var typeInfo = await GetTypeInfo(typeId, token); if (typeInfo.FieldsList != null) { return typeInfo.FieldsList; } var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetFields, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetFields, commandParamsWriter, token); var nFields = retDebuggerCmdReader.ReadInt32(); for (int i = 0 ; i < nFields; i++) @@ -1257,37 +1256,42 @@ public async Task> GetTypeFields(SessionId sessionId, int t return ret; } - public string ReplaceCommonClassNames(string className) - { - className = className.Replace("System.String", "string"); - className = className.Replace("System.Boolean", "bool"); - className = className.Replace("System.Char", "char"); - className = className.Replace("System.Int32", "int"); - className = className.Replace("System.Object", "object"); - className = className.Replace("System.Void", "void"); - className = className.Replace("System.Byte", "byte"); - return className; - } - - internal async Task GetCAttrsFromType(SessionId sessionId, int objectId, int typeId, string attrName, CancellationToken token) - { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + public string ReplaceCommonClassNames(string className) => + new StringBuilder(className) + .Replace("System.String", "string") + .Replace("System.Boolean", "bool") + .Replace("System.Char", "char") + .Replace("System.SByte", "sbyte") + .Replace("System.Int32", "int") + .Replace("System.Int64", "long") + .Replace("System.Single", "float") + .Replace("System.Double", "double") + .Replace("System.Byte", "byte") + .Replace("System.UInt16", "ushort") + .Replace("System.UInt32", "uint") + .Replace("System.UInt64", "ulong") + .Replace("System.Object", "object") + .Replace("System.Void", "void") + //.Replace("System.Decimal", "decimal") + .ToString(); + + internal async Task GetCAttrsFromType(int objectId, int typeId, string attrName, CancellationToken token) + { + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); commandParamsWriter.Write(0); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetCattrs, commandParams, token); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetCattrs, commandParamsWriter, token); var count = retDebuggerCmdReader.ReadInt32(); if (count == 0) return null; for (int i = 0 ; i < count; i++) { var methodId = retDebuggerCmdReader.ReadInt32(); - commandParams = new MemoryStream(); - commandParamsWriter = new MonoBinaryWriter(commandParams); - commandParamsWriter.Write(methodId); - var retDebuggerCmdReader2 = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetDeclaringType, commandParams, token); + using var commandCattrParamsWriter = new MonoBinaryWriter(); + commandCattrParamsWriter.Write(methodId); + using var retDebuggerCmdReader2 = await SendDebuggerAgentCommand(CmdMethod.GetDeclaringType, commandCattrParamsWriter, token); var customAttributeTypeId = retDebuggerCmdReader2.ReadInt32(); - var customAttributeName = await GetTypeName(sessionId, customAttributeTypeId, token); + var customAttributeName = await GetTypeName(customAttributeTypeId, token); if (customAttributeName == attrName) return retDebuggerCmdReader; @@ -1298,20 +1302,19 @@ internal async Task GetCAttrsFromType(SessionId sessionId, int for (int j = 0; j < parmCount; j++) { //to typed_args - await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "varName", false, -1, false, token); + await CreateJObjectForVariableValue(retDebuggerCmdReader, "varName", false, -1, false, token); } } } return null; } - public async Task GetAssemblyFromType(SessionId sessionId, int type_id, CancellationToken token) + public async Task GetAssemblyFromType(int type_id, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(type_id); commandParamsWriter.Write((int) MonoTypeNameFormat.FormatReflection); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadString(); retDebuggerCmdReader.ReadString(); @@ -1320,11 +1323,11 @@ public async Task GetAssemblyFromType(SessionId sessionId, int type_id, Can return retDebuggerCmdReader.ReadInt32(); } - public async Task GetValueFromDebuggerDisplayAttribute(SessionId sessionId, int objectId, int typeId, CancellationToken token) + public async Task GetValueFromDebuggerDisplayAttribute(int objectId, int typeId, CancellationToken token) { string expr = ""; try { - var getCAttrsRetReader = await GetCAttrsFromType(sessionId, objectId, typeId, "System.Diagnostics.DebuggerDisplayAttribute", token); + var getCAttrsRetReader = await GetCAttrsFromType(objectId, typeId, "System.Diagnostics.DebuggerDisplayAttribute", token); if (getCAttrsRetReader == null) return null; @@ -1334,9 +1337,9 @@ public async Task GetValueFromDebuggerDisplayAttribute(SessionId session return null; var stringId = getCAttrsRetReader.ReadInt32(); - var dispAttrStr = await GetStringValue(sessionId, stringId, token); + var dispAttrStr = await GetStringValue(stringId, token); ExecutionContext context = proxy.GetContext(sessionId); - JArray objectValues = await GetObjectValues(sessionId, objectId, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.ForDebuggerDisplayAttribute, token); + JArray objectValues = await GetObjectValues(objectId, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.ForDebuggerDisplayAttribute, token); var thisObj = CreateJObject(value: "", type: "object", description: "", writable: false, objectId: $"dotnet:object:{objectId}"); thisObj["name"] = "this"; @@ -1363,14 +1366,14 @@ public async Task GetValueFromDebuggerDisplayAttribute(SessionId session } catch (Exception) { - logger.LogDebug($"Could not evaluate DebuggerDisplayAttribute - {expr} - {await GetTypeName(sessionId, typeId, token)}"); + logger.LogDebug($"Could not evaluate DebuggerDisplayAttribute - {expr} - {await GetTypeName(typeId, token)}"); } return null; } - public async Task GetTypeName(SessionId sessionId, int typeId, CancellationToken token) + public async Task GetTypeName(int typeId, CancellationToken token) { - string className = await GetTypeNameOriginal(sessionId, typeId, token); + string className = await GetTypeNameOriginal(typeId, token); className = className.Replace("+", "."); className = Regex.Replace(className, @"`\d+", ""); className = Regex.Replace(className, @"[[, ]+]", "__SQUARED_BRACKETS__"); @@ -1383,25 +1386,23 @@ public async Task GetTypeName(SessionId sessionId, int typeId, Cancellat return className; } - public async Task GetTypeNameOriginal(SessionId sessionId, int typeId, CancellationToken token) + public async Task GetTypeNameOriginal(int typeId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); commandParamsWriter.Write((int) MonoTypeNameFormat.FormatReflection); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadString(); //namespace retDebuggerCmdReader.ReadString(); //class name return retDebuggerCmdReader.ReadString(); //class name formatted } - public async Task GetTypeToken(SessionId sessionId, int typeId, CancellationToken token) + public async Task GetTypeToken(int typeId, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeId); commandParamsWriter.Write((int) MonoTypeNameFormat.FormatReflection); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetInfo, commandParamsWriter, token); retDebuggerCmdReader.ReadString(); //namespace retDebuggerCmdReader.ReadString(); //class name retDebuggerCmdReader.ReadString(); //class name formatted @@ -1412,25 +1413,23 @@ public async Task GetTypeToken(SessionId sessionId, int typeId, Cancellatio return retDebuggerCmdReader.ReadInt32(); //token } - public async Task GetStringValue(SessionId sessionId, int string_id, CancellationToken token) + public async Task GetStringValue(int string_id, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(string_id); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdString.GetValue, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdString.GetValue, commandParamsWriter, token); var isUtf16 = retDebuggerCmdReader.ReadByte(); if (isUtf16 == 0) { return retDebuggerCmdReader.ReadString(); } return null; } - public async Task GetArrayDimensions(SessionId sessionId, int object_id, CancellationToken token) + public async Task GetArrayDimensions(int object_id, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(object_id); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetLength, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdArray.GetLength, commandParamsWriter, token); var length = retDebuggerCmdReader.ReadInt32(); var rank = new int[length]; for (int i = 0 ; i < length; i++) @@ -1440,115 +1439,107 @@ public async Task GetArrayDimensions(SessionId sessionId, int o } return new ArrayDimensions(rank); } - public async Task> GetTypeIdFromObject(SessionId sessionId, int object_id, bool withParents, CancellationToken token) + public async Task> GetTypeIdFromObject(int object_id, bool withParents, CancellationToken token) { List ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(object_id); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefGetType, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdObject.RefGetType, commandParamsWriter, token); var type_id = retDebuggerCmdReader.ReadInt32(); ret.Add(type_id); if (withParents) { - commandParams = new MemoryStream(); - commandParamsWriter = new MonoBinaryWriter(commandParams); - commandParamsWriter.Write(type_id); - retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetParents, commandParams, token); - var parentsCount = retDebuggerCmdReader.ReadInt32(); + using var commandParentsParamsWriter = new MonoBinaryWriter(); + commandParentsParamsWriter.Write(type_id); + using var parentsCmdReader = await SendDebuggerAgentCommand(CmdType.GetParents, commandParentsParamsWriter, token); + var parentsCount = parentsCmdReader.ReadInt32(); for (int i = 0 ; i < parentsCount; i++) { - ret.Add(retDebuggerCmdReader.ReadInt32()); + ret.Add(parentsCmdReader.ReadInt32()); } } return ret; } - public async Task GetClassNameFromObject(SessionId sessionId, int object_id, CancellationToken token) + public async Task GetClassNameFromObject(int object_id, CancellationToken token) { - var type_id = await GetTypeIdFromObject(sessionId, object_id, false, token); - return await GetTypeName(sessionId, type_id[0], token); + var type_id = await GetTypeIdFromObject(object_id, false, token); + return await GetTypeName(type_id[0], token); } - public async Task GetTypeIdFromToken(SessionId sessionId, int assemblyId, int typeToken, CancellationToken token) + public async Task GetTypeIdFromToken(int assemblyId, int typeToken, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((int)assemblyId); commandParamsWriter.Write((int)typeToken); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetTypeFromToken, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdAssembly.GetTypeFromToken, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task GetMethodIdByName(SessionId sessionId, int type_id, string method_name, CancellationToken token) + public async Task GetMethodIdByName(int type_id, string method_name, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((int)type_id); 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); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetMethodsByNameFlags, commandParamsWriter, token); var nMethods = retDebuggerCmdReader.ReadInt32(); return retDebuggerCmdReader.ReadInt32(); } - public async Task IsDelegate(SessionId sessionId, int objectId, CancellationToken token) + public async Task IsDelegate(int objectId, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((int)objectId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefIsDelegate, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdObject.RefIsDelegate, commandParamsWriter, token); return retDebuggerCmdReader.ReadByte() == 1; } - public async Task GetDelegateMethod(SessionId sessionId, int objectId, CancellationToken token) + public async Task GetDelegateMethod(int objectId, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((int)objectId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefDelegateGetMethod, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdObject.RefDelegateGetMethod, commandParamsWriter, token); return retDebuggerCmdReader.ReadInt32(); } - public async Task GetDelegateMethodDescription(SessionId sessionId, int objectId, CancellationToken token) + public async Task GetDelegateMethodDescription(int objectId, CancellationToken token) { - var methodId = await GetDelegateMethod(sessionId, objectId, token); + var methodId = await GetDelegateMethod(objectId, token); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); //Console.WriteLine("methodId - " + methodId); if (methodId == 0) return ""; - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetName, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.GetName, commandParamsWriter, token); var methodName = retDebuggerCmdReader.ReadString(); - var returnType = await GetReturnType(sessionId, methodId, token); - var parameters = await GetParameters(sessionId, methodId, token); + var returnType = await GetReturnType(methodId, token); + var parameters = await GetParameters(methodId, token); return $"{returnType} {methodName} {parameters}"; } - public async Task InvokeMethod(SessionId sessionId, byte[] valueTypeBuffer, int methodId, string varName, CancellationToken token) + public async Task InvokeMethod(ArraySegment valueTypeBuffer, int methodId, string varName, CancellationToken token) { - MemoryStream parms = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(parms); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); commandParamsWriter.Write(valueTypeBuffer); commandParamsWriter.Write(0); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.InvokeMethod, parms, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdVM.InvokeMethod, commandParamsWriter, token); retDebuggerCmdReader.ReadByte(); //number of objects returned. - return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, varName, false, -1, false, token); + return await CreateJObjectForVariableValue(retDebuggerCmdReader, varName, false, -1, false, token); } - public async Task GetPropertyMethodIdByName(SessionId sessionId, int typeId, string propertyName, CancellationToken token) + public async Task GetPropertyMethodIdByName(int typeId, string propertyName, CancellationToken token) { - var retDebuggerCmdReader = await GetTypePropertiesReader(sessionId, typeId, token); + using var retDebuggerCmdReader = await GetTypePropertiesReader(typeId, token); if (retDebuggerCmdReader == null) return -1; @@ -1568,10 +1559,10 @@ public async Task GetPropertyMethodIdByName(SessionId sessionId, int typeId return -1; } - public async Task CreateJArrayForProperties(SessionId sessionId, int typeId, byte[] object_buffer, JArray attributes, bool isAutoExpandable, string objectId, bool isOwn, CancellationToken token) + public async Task CreateJArrayForProperties(int typeId, ArraySegment object_buffer, JArray attributes, bool isAutoExpandable, string objectId, bool isOwn, CancellationToken token) { JArray ret = new JArray(); - var retDebuggerCmdReader = await GetTypePropertiesReader(sessionId, typeId, token); + using var retDebuggerCmdReader = await GetTypePropertiesReader(typeId, token); if (retDebuggerCmdReader == null) return null; @@ -1583,7 +1574,7 @@ public async Task CreateJArrayForProperties(SessionId sessionId, int typ var getMethodId = retDebuggerCmdReader.ReadInt32(); retDebuggerCmdReader.ReadInt32(); //setmethod var attrs = retDebuggerCmdReader.ReadInt32(); //attrs - if (getMethodId == 0 || await GetParamCount(sessionId, getMethodId, token) != 0 || await MethodIsStatic(sessionId, getMethodId, token)) + if (getMethodId == 0 || await GetParamCount(getMethodId, token) != 0 || await MethodIsStatic(getMethodId, token)) continue; JObject propRet = null; if (attributes.Where(attribute => attribute["name"].Value().Equals(propertyNameStr)).Any()) @@ -1591,7 +1582,7 @@ public async Task CreateJArrayForProperties(SessionId sessionId, int typ if (isAutoExpandable) { try { - propRet = await InvokeMethod(sessionId, object_buffer, getMethodId, propertyNameStr, token); + propRet = await InvokeMethod(object_buffer, getMethodId, propertyNameStr, token); } catch (Exception) { @@ -1619,28 +1610,26 @@ public async Task CreateJArrayForProperties(SessionId sessionId, int typ } return ret; } - public async Task GetPointerContent(SessionId sessionId, int pointerId, CancellationToken token) + public async Task GetPointerContent(int pointerId, CancellationToken token) { var ret = new List(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(pointerValues[pointerId].address); commandParamsWriter.Write(pointerValues[pointerId].typeId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdPointer.GetValue, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdPointer.GetValue, commandParamsWriter, token); var varName = pointerValues[pointerId].varName; if (int.TryParse(varName, out _)) varName = $"[{varName}]"; - return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "*" + varName, false, -1, false, token); + return await CreateJObjectForVariableValue(retDebuggerCmdReader, "*" + varName, false, -1, false, token); } - public async Task GetPropertiesValuesOfValueType(SessionId sessionId, int valueTypeId, CancellationToken token) + public async Task GetPropertiesValuesOfValueType(int valueTypeId, CancellationToken token) { JArray ret = new JArray(); var valueType = valueTypes[valueTypeId]; - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(valueType.typeId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetParents, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdType.GetParents, commandParamsWriter, token); var parentsCount = retDebuggerCmdReader.ReadInt32(); List typesToGetProperties = new List(); typesToGetProperties.Add(valueType.typeId); @@ -1650,7 +1639,7 @@ public async Task GetPropertiesValuesOfValueType(SessionId sessionId, in } for (int i = 0 ; i < typesToGetProperties.Count; i++) { - var properties = await CreateJArrayForProperties(sessionId, typesToGetProperties[i], valueType.valueTypeBuffer, valueType.valueTypeJson, valueType.valueTypeAutoExpand, $"dotnet:valuetype:{valueType.Id}", i == 0, token); + var properties = await CreateJArrayForProperties(typesToGetProperties[i], valueType.valueTypeBuffer, valueType.valueTypeJson, valueType.valueTypeAutoExpand, $"dotnet:valuetype:{valueType.Id}", i == 0, token); ret = new JArray(ret.Union(properties)); } @@ -1719,7 +1708,7 @@ public JObject CreateJObjectForChar(int value) return CreateJObject(description, "symbol", description, true); } - public async Task CreateJObjectForPtr(SessionId sessionId, ElementType etype, MonoBinaryReader retDebuggerCmdReader, string name, CancellationToken token) + public async Task CreateJObjectForPtr(ElementType etype, MonoBinaryReader retDebuggerCmdReader, string name, CancellationToken token) { string type; string value; @@ -1729,7 +1718,7 @@ public async Task CreateJObjectForPtr(SessionId sessionId, ElementType if (etype == ElementType.FnPtr) className = "(*())"; //to keep the old behavior else - className = "(" + await GetTypeName(sessionId, typeId, token) + ")"; + className = "(" + await GetTypeName(typeId, token) + ")"; int pointerId = 0; if (valueAddress != 0 && className != "(void*)") @@ -1747,19 +1736,19 @@ public async Task CreateJObjectForPtr(SessionId sessionId, ElementType return CreateJObject(value, type, value, false, className, $"dotnet:pointer:{pointerId}", "pointer"); } - public async Task CreateJObjectForString(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) + public async Task CreateJObjectForString(MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { var string_id = retDebuggerCmdReader.ReadInt32(); - var value = await GetStringValue(sessionId, string_id, token); + var value = await GetStringValue(string_id, token); return CreateJObject(value, "string", value, false); } - public async Task CreateJObjectForArray(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) + public async Task CreateJObjectForArray(MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { var objectId = retDebuggerCmdReader.ReadInt32(); - var className = await GetClassNameFromObject(sessionId, objectId, token); + var className = await GetClassNameFromObject(objectId, token); var arrayType = className.ToString(); - var length = await GetArrayDimensions(sessionId, objectId, token); + var length = await GetArrayDimensions(objectId, token); if (arrayType.LastIndexOf('[') > 0) arrayType = arrayType.Insert(arrayType.LastIndexOf('[')+1, length.ToString()); if (className.LastIndexOf('[') > 0) @@ -1767,28 +1756,28 @@ public async Task CreateJObjectForArray(SessionId sessionId, MonoBinary return CreateJObject(null, "object", description : arrayType, writable : false, className.ToString(), "dotnet:array:" + objectId, null, subtype : length.Rank == 1 ? "array" : null); } - public async Task CreateJObjectForObject(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, int typeIdFromAttribute, bool forDebuggerDisplayAttribute, CancellationToken token) + public async Task CreateJObjectForObject(MonoBinaryReader retDebuggerCmdReader, int typeIdFromAttribute, bool forDebuggerDisplayAttribute, CancellationToken token) { var objectId = retDebuggerCmdReader.ReadInt32(); var className = ""; - var type_id = await GetTypeIdFromObject(sessionId, objectId, false, token); - className = await GetTypeName(sessionId, type_id[0], token); + var type_id = await GetTypeIdFromObject(objectId, false, token); + className = await GetTypeName(type_id[0], token); string debuggerDisplayAttribute = null; if (!forDebuggerDisplayAttribute) - debuggerDisplayAttribute = await GetValueFromDebuggerDisplayAttribute(sessionId, objectId, type_id[0], token); + debuggerDisplayAttribute = await GetValueFromDebuggerDisplayAttribute(objectId, type_id[0], token); var description = className.ToString(); if (debuggerDisplayAttribute != null) description = debuggerDisplayAttribute; - if (await IsDelegate(sessionId, objectId, token)) + if (await IsDelegate(objectId, token)) { if (typeIdFromAttribute != -1) { - className = await GetTypeName(sessionId, typeIdFromAttribute, token); + className = await GetTypeName(typeIdFromAttribute, token); } - description = await GetDelegateMethodDescription(sessionId, objectId, token); + description = await GetDelegateMethodDescription(objectId, token); if (description == "") { return CreateJObject(className.ToString(), "symbol", className.ToString(), false); @@ -1797,22 +1786,22 @@ public async Task CreateJObjectForObject(SessionId sessionId, MonoBinar return CreateJObject(null, "object", description, false, className, $"dotnet:object:{objectId}"); } - public async Task CreateJObjectForValueType(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, string name, long initialPos, CancellationToken token) + public async Task CreateJObjectForValueType(MonoBinaryReader retDebuggerCmdReader, string name, long initialPos, CancellationToken token) { JObject fieldValueType = null; var isEnum = retDebuggerCmdReader.ReadByte(); var isBoxed = retDebuggerCmdReader.ReadByte() == 1; var typeId = retDebuggerCmdReader.ReadInt32(); - var className = await GetTypeName(sessionId, typeId, token); + var className = await GetTypeName(typeId, token); var description = className; var numFields = retDebuggerCmdReader.ReadInt32(); - var fields = await GetTypeFields(sessionId, typeId, token); + var fields = await GetTypeFields(typeId, token); JArray valueTypeFields = new JArray(); if (className.IndexOf("System.Nullable<") == 0) //should we call something on debugger-agent to check??? { retDebuggerCmdReader.ReadByte(); //ignoring the boolean type var isNull = retDebuggerCmdReader.ReadInt32(); - var value = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, name, false, -1, false, token); + var value = await CreateJObjectForVariableValue(retDebuggerCmdReader, name, false, -1, false, token); if (isNull != 0) return value; else @@ -1820,7 +1809,7 @@ public async Task CreateJObjectForValueType(SessionId sessionId, MonoBi } for (int i = 0; i < numFields ; i++) { - fieldValueType = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, fields.ElementAt(i).Name, true, fields.ElementAt(i).TypeId, false, token); + fieldValueType = await CreateJObjectForVariableValue(retDebuggerCmdReader, fields.ElementAt(i).Name, true, fields.ElementAt(i).TypeId, false, token); valueTypeFields.Add(fieldValueType); } @@ -1833,8 +1822,8 @@ public async Task CreateJObjectForValueType(SessionId sessionId, MonoBi retDebuggerCmdReader.BaseStream.Position = endPos; valueTypes[valueTypeId] = new ValueTypeClass(name, valueTypeBuffer, valueTypeFields, typeId, AutoExpandable(className), valueTypeId); if (AutoInvokeToString(className) || isEnum == 1) { - int methodId = await GetMethodIdByName(sessionId, typeId, "ToString", token); - var retMethod = await InvokeMethod(sessionId, valueTypeBuffer, methodId, "methodRet", token); + int methodId = await GetMethodIdByName(typeId, "ToString", token); + var retMethod = await InvokeMethod(valueTypeBuffer, methodId, "methodRet", token); description = retMethod["value"]?["value"].Value(); if (className.Equals("System.Guid")) description = description.ToUpper(); //to keep the old behavior @@ -1845,7 +1834,7 @@ public async Task CreateJObjectForValueType(SessionId sessionId, MonoBi return CreateJObject(null, "object", description, false, className, $"dotnet:valuetype:{valueTypeId}", null, null, true, true, isEnum == 1); } - public async Task CreateJObjectForNull(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) + public async Task CreateJObjectForNull(MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { string className = ""; ElementType variableType = (ElementType)retDebuggerCmdReader.ReadByte(); @@ -1855,7 +1844,7 @@ public async Task CreateJObjectForNull(SessionId sessionId, MonoBinaryR case ElementType.Class: { var type_id = retDebuggerCmdReader.ReadInt32(); - className = await GetTypeName(sessionId, type_id, token); + className = await GetTypeName(type_id, token); break; } @@ -1868,20 +1857,20 @@ public async Task CreateJObjectForNull(SessionId sessionId, MonoBinaryR var internal_type_id = retDebuggerCmdReader.ReadInt32(); } var type_id = retDebuggerCmdReader.ReadInt32(); - className = await GetTypeName(sessionId, type_id, token); + className = await GetTypeName(type_id, token); break; } default: { var type_id = retDebuggerCmdReader.ReadInt32(); - className = await GetTypeName(sessionId, type_id, token); + className = await GetTypeName(type_id, token); break; } } return CreateJObject(null, "object", className, false, className, null, null, "null"); } - public async Task CreateJObjectForVariableValue(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, string name, bool isOwn, int typeIdFromAttribute, bool forDebuggerDisplayAttribute, CancellationToken token) + public async Task CreateJObjectForVariableValue(MonoBinaryReader retDebuggerCmdReader, string name, bool isOwn, int typeIdFromAttribute, bool forDebuggerDisplayAttribute, CancellationToken token) { long initialPos = retDebuggerCmdReader == null ? 0 : retDebuggerCmdReader.BaseStream.Position; ElementType etype = (ElementType)retDebuggerCmdReader.ReadByte(); @@ -1970,34 +1959,34 @@ public async Task CreateJObjectForVariableValue(SessionId sessionId, Mo case ElementType.FnPtr: case ElementType.Ptr: { - ret = await CreateJObjectForPtr(sessionId, etype, retDebuggerCmdReader, name, token); + ret = await CreateJObjectForPtr(etype, retDebuggerCmdReader, name, token); break; } case ElementType.String: { - ret = await CreateJObjectForString(sessionId, retDebuggerCmdReader, token); + ret = await CreateJObjectForString(retDebuggerCmdReader, token); break; } case ElementType.SzArray: case ElementType.Array: { - ret = await CreateJObjectForArray(sessionId, retDebuggerCmdReader, token); + ret = await CreateJObjectForArray(retDebuggerCmdReader, token); break; } case ElementType.Class: case ElementType.Object: { - ret = await CreateJObjectForObject(sessionId, retDebuggerCmdReader, typeIdFromAttribute, forDebuggerDisplayAttribute, token); + ret = await CreateJObjectForObject(retDebuggerCmdReader, typeIdFromAttribute, forDebuggerDisplayAttribute, token); break; } case ElementType.ValueType: { - ret = await CreateJObjectForValueType(sessionId, retDebuggerCmdReader, name, initialPos, token); + ret = await CreateJObjectForValueType(retDebuggerCmdReader, name, initialPos, token); break; } case (ElementType)ValueTypeId.Null: { - ret = await CreateJObjectForNull(sessionId, retDebuggerCmdReader, token); + ret = await CreateJObjectForNull(retDebuggerCmdReader, token); break; } case (ElementType)ValueTypeId.Type: @@ -2020,19 +2009,18 @@ public async Task CreateJObjectForVariableValue(SessionId sessionId, Mo return ret; } - public async Task IsAsyncMethod(SessionId sessionId, int methodId, CancellationToken token) + public async Task IsAsyncMethod(int methodId, CancellationToken token) { - var methodInfo = await GetMethodInfo(sessionId, methodId, token); + var methodInfo = await GetMethodInfo(methodId, token); if (methodInfo != null && methodInfo.Info.IsAsync != -1) { return methodInfo.Info.IsAsync == 1; } - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(methodId); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.AsyncDebugInfo, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdMethod.AsyncDebugInfo, commandParamsWriter, token); methodInfo.Info.IsAsync = retDebuggerCmdReader.ReadByte(); return methodInfo.Info.IsAsync == 1; } @@ -2049,7 +2037,7 @@ private bool IsClosureReferenceField (string fieldName) fieldName.StartsWith ("<>8__", StringComparison.Ordinal); } - public async Task GetHoistedLocalVariables(SessionId sessionId, int objectId, JArray asyncLocals, CancellationToken token) + public async Task GetHoistedLocalVariables(int objectId, JArray asyncLocals, CancellationToken token) { JArray asyncLocalsFull = new JArray(); List objectsAlreadyRead = new(); @@ -2068,8 +2056,8 @@ public async Task GetHoistedLocalVariables(SessionId sessionId, int obje { if (int.TryParse(dotnetObjectId.Value, out int objectIdToGetInfo) && !objectsAlreadyRead.Contains(objectIdToGetInfo)) { - var asyncLocalsFromObject = await GetObjectValues(sessionId, objectIdToGetInfo, GetObjectCommandOptions.WithProperties, token); - var hoistedLocalVariable = await GetHoistedLocalVariables(sessionId, objectIdToGetInfo, asyncLocalsFromObject, token); + var asyncLocalsFromObject = await GetObjectValues(objectIdToGetInfo, GetObjectCommandOptions.WithProperties, token); + var hoistedLocalVariable = await GetHoistedLocalVariables(objectIdToGetInfo, asyncLocalsFromObject, token); asyncLocalsFull = new JArray(asyncLocalsFull.Union(hoistedLocalVariable)); } } @@ -2093,11 +2081,9 @@ public async Task GetHoistedLocalVariables(SessionId sessionId, int obje return asyncLocalsFull; } - public async Task StackFrameGetValues(SessionId sessionId, MethodInfoWithDebugInformation method, int thread_id, int frame_id, VarInfo[] varIds, CancellationToken token) + public async Task StackFrameGetValues(MethodInfoWithDebugInformation method, int thread_id, int frame_id, VarInfo[] varIds, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); - MonoBinaryReader retDebuggerCmdReader = null; + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(thread_id); commandParamsWriter.Write(frame_id); commandParamsWriter.Write(varIds.Length); @@ -2106,27 +2092,27 @@ public async Task StackFrameGetValues(SessionId sessionId, MethodInfoWit commandParamsWriter.Write(var.Index); } - if (await IsAsyncMethod(sessionId, method.DebugId, token)) + if (await IsAsyncMethod(method.DebugId, token)) { - retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetThis, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdFrame.GetThis, commandParamsWriter, token); retDebuggerCmdReader.ReadByte(); //ignore type var objectId = retDebuggerCmdReader.ReadInt32(); - var asyncLocals = await GetObjectValues(sessionId, objectId, GetObjectCommandOptions.WithProperties, token); - asyncLocals = await GetHoistedLocalVariables(sessionId, objectId, asyncLocals, token); + var asyncLocals = await GetObjectValues(objectId, GetObjectCommandOptions.WithProperties, token); + asyncLocals = await GetHoistedLocalVariables(objectId, asyncLocals, token); return asyncLocals; } JArray locals = new JArray(); - retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetValues, commandParams, token); + using var localsDebuggerCmdReader = await SendDebuggerAgentCommand(CmdFrame.GetValues, commandParamsWriter, token); foreach (var var in varIds) { - var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, var.Name, false, -1, false, token); + var var_json = await CreateJObjectForVariableValue(localsDebuggerCmdReader, var.Name, false, -1, false, token); locals.Add(var_json); } if (!method.Info.IsStatic()) { - retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetThis, commandParams, token); - var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "this", false, -1, false, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdFrame.GetThis, commandParamsWriter, token); + var var_json = await CreateJObjectForVariableValue(retDebuggerCmdReader, "this", false, -1, false, token); var_json.Add("fieldOffset", -1); locals.Add(var_json); } @@ -2134,11 +2120,11 @@ public async Task StackFrameGetValues(SessionId sessionId, MethodInfoWit } - public async Task GetValueTypeValues(SessionId sessionId, int valueTypeId, bool accessorPropertiesOnly, CancellationToken token) + public async Task GetValueTypeValues(int valueTypeId, bool accessorPropertiesOnly, CancellationToken token) { if (valueTypes[valueTypeId].valueTypeJsonProps == null) { - valueTypes[valueTypeId].valueTypeJsonProps = await GetPropertiesValuesOfValueType(sessionId, valueTypeId, token); + valueTypes[valueTypeId].valueTypeJsonProps = await GetPropertiesValuesOfValueType(valueTypeId, token); } if (accessorPropertiesOnly) return valueTypes[valueTypeId].valueTypeJsonProps; @@ -2146,13 +2132,13 @@ public async Task GetValueTypeValues(SessionId sessionId, int valueTypeI return ret; } - public async Task GetValueTypeProxy(SessionId sessionId, int valueTypeId, CancellationToken token) + public async Task GetValueTypeProxy(int valueTypeId, CancellationToken token) { if (valueTypes[valueTypeId].valueTypeProxy != null) return valueTypes[valueTypeId].valueTypeProxy; valueTypes[valueTypeId].valueTypeProxy = new JArray(valueTypes[valueTypeId].valueTypeJson); - var retDebuggerCmdReader = await GetTypePropertiesReader(sessionId, valueTypes[valueTypeId].typeId, token); + var retDebuggerCmdReader = await GetTypePropertiesReader(valueTypes[valueTypeId].typeId, token); if (retDebuggerCmdReader == null) return null; @@ -2166,19 +2152,19 @@ public async Task GetValueTypeProxy(SessionId sessionId, int valueTypeId var getMethodId = retDebuggerCmdReader.ReadInt32(); retDebuggerCmdReader.ReadInt32(); //setmethod retDebuggerCmdReader.ReadInt32(); //attrs - if (await MethodIsStatic(sessionId, getMethodId, token)) + if (await MethodIsStatic(getMethodId, token)) continue; - var command_params_to_proxy = new MemoryStream(); - var command_params_writer_to_proxy = new MonoBinaryWriter(command_params_to_proxy); + using var command_params_writer_to_proxy = new MonoBinaryWriter(); command_params_writer_to_proxy.Write(getMethodId); command_params_writer_to_proxy.Write(valueTypes[valueTypeId].valueTypeBuffer); command_params_writer_to_proxy.Write(0); + var (data, length) = command_params_writer_to_proxy.ToBase64(); valueTypes[valueTypeId].valueTypeProxy.Add(JObject.FromObject(new { get = JObject.FromObject(new { commandSet = CommandSet.Vm, command = CmdVM.InvokeMethod, - buffer = Convert.ToBase64String(command_params_to_proxy.ToArray()), - length = command_params_to_proxy.ToArray().Length + buffer = data, + length = length, }), name = propertyNameStr })); @@ -2186,36 +2172,35 @@ public async Task GetValueTypeProxy(SessionId sessionId, int valueTypeId return valueTypes[valueTypeId].valueTypeProxy; } - public async Task GetArrayValues(SessionId sessionId, int arrayId, CancellationToken token) + public async Task GetArrayValues(int arrayId, CancellationToken token) { - var dimensions = await GetArrayDimensions(sessionId, arrayId, token); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + var dimensions = await GetArrayDimensions(arrayId, token); + var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(arrayId); commandParamsWriter.Write(0); commandParamsWriter.Write(dimensions.TotalLength); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetValues, commandParams, token); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdArray.GetValues, commandParamsWriter, token); JArray array = new JArray(); for (int i = 0 ; i < dimensions.TotalLength; i++) { - var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, dimensions.GetArrayIndexString(i), isOwn : false, -1, forDebuggerDisplayAttribute : false, token); + var var_json = await CreateJObjectForVariableValue(retDebuggerCmdReader, dimensions.GetArrayIndexString(i), isOwn : false, -1, forDebuggerDisplayAttribute : false, token); array.Add(var_json); } return array; } - public async Task GetArrayValuesProxy(SessionId sessionId, int arrayId, CancellationToken token) + public async Task GetArrayValuesProxy(int arrayId, CancellationToken token) { - var length = await GetArrayDimensions(sessionId, arrayId, token); + var length = await GetArrayDimensions(arrayId, token); var arrayProxy = JObject.FromObject(new { - items = await GetArrayValues(sessionId, arrayId, token), + items = await GetArrayValues(arrayId, token), dimensionsDetails = length.Bounds }); return arrayProxy; } - public async Task EnableExceptions(SessionId sessionId, PauseOnExceptionsKind state, CancellationToken token) + public async Task EnableExceptions(PauseOnExceptionsKind state, CancellationToken token) { if (state == PauseOnExceptionsKind.Unset) { @@ -2223,8 +2208,7 @@ public async Task EnableExceptions(SessionId sessionId, PauseOnExceptionsK return false; } - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write((byte)EventKind.Exception); commandParamsWriter.Write((byte)SuspendPolicy.None); commandParamsWriter.Write((byte)1); @@ -2243,29 +2227,27 @@ public async Task EnableExceptions(SessionId sessionId, PauseOnExceptionsK commandParamsWriter.Write((byte)1);//subclasses commandParamsWriter.Write((byte)0);//not_filtered_feature commandParamsWriter.Write((byte)0);//everything_else - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Set, commandParamsWriter, token); return true; } - public async Task GetTypeByName(SessionId sessionId, string typeToSearch, CancellationToken token) + public async Task GetTypeByName(string typeToSearch, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(typeToSearch); - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.GetTypes, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdVM.GetTypes, commandParamsWriter, token); var count = retDebuggerCmdReader.ReadInt32(); //count ret return retDebuggerCmdReader.ReadInt32(); } - public async Task GetValuesFromDebuggerProxyAttribute(SessionId sessionId, int objectId, int typeId, CancellationToken token) + public async Task GetValuesFromDebuggerProxyAttribute(int objectId, int typeId, CancellationToken token) { try { - var getCAttrsRetReader = await GetCAttrsFromType(sessionId, objectId, typeId, "System.Diagnostics.DebuggerTypeProxyAttribute", token); + var getCAttrsRetReader = await GetCAttrsFromType(objectId, typeId, "System.Diagnostics.DebuggerTypeProxyAttribute", token); var methodId = -1; if (getCAttrsRetReader == null) return null; - var invokeParams = new MemoryStream(); - var invokeParamsWriter = new MonoBinaryWriter(invokeParams); + using var invokeParamsWriter = new MonoBinaryWriter(); invokeParamsWriter.Write((byte)ValueTypeId.Null); invokeParamsWriter.Write((byte)0); //not used invokeParamsWriter.Write(0); //not used @@ -2277,23 +2259,22 @@ public async Task GetValuesFromDebuggerProxyAttribute(SessionId sessionI if ((ValueTypeId)monoTypeId != ValueTypeId.Type) continue; var cAttrTypeId = getCAttrsRetReader.ReadInt32(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(cAttrTypeId); - var className = await GetTypeNameOriginal(sessionId, cAttrTypeId, token); + var className = await GetTypeNameOriginal(cAttrTypeId, token); if (className.IndexOf('[') > 0) { className = className.Remove(className.IndexOf('[')); - var assemblyId = await GetAssemblyIdFromType(sessionId, cAttrTypeId, token); - var assemblyName = await GetFullAssemblyName(sessionId, assemblyId, token); + var assemblyId = await GetAssemblyIdFromType(cAttrTypeId, token); + var assemblyName = await GetFullAssemblyName(assemblyId, token); var typeToSearch = className; typeToSearch += "[["; //System.Collections.Generic.List`1[[System.Int32,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]],mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - List genericTypeArgs = await GetTypeParamsOrArgsForGenericType(sessionId, typeId, token); + List genericTypeArgs = await GetTypeParamsOrArgsForGenericType(typeId, token); for (int k = 0; k < genericTypeArgs.Count; k++) { - var assemblyIdArg = await GetAssemblyIdFromType(sessionId, genericTypeArgs[k], token); - var assemblyNameArg = await GetFullAssemblyName(sessionId, assemblyIdArg, token); - var classNameArg = await GetTypeNameOriginal(sessionId, genericTypeArgs[k], token); + var assemblyIdArg = await GetAssemblyIdFromType(genericTypeArgs[k], token); + var assemblyNameArg = await GetFullAssemblyName(assemblyIdArg, token); + var classNameArg = await GetTypeNameOriginal(genericTypeArgs[k], token); typeToSearch += classNameArg +", " + assemblyNameArg; if (k + 1 < genericTypeArgs.Count) typeToSearch += "], ["; @@ -2302,43 +2283,43 @@ public async Task GetValuesFromDebuggerProxyAttribute(SessionId sessionI } typeToSearch += "]"; typeToSearch += ", " + assemblyName; - var genericTypeId = await GetTypeByName(sessionId, typeToSearch, token); + var genericTypeId = await GetTypeByName(typeToSearch, token); if (genericTypeId < 0) return null; - methodId = await GetMethodIdByName(sessionId, genericTypeId, ".ctor", token); + methodId = await GetMethodIdByName(genericTypeId, ".ctor", token); } else - methodId = await GetMethodIdByName(sessionId, cAttrTypeId, ".ctor", token); + methodId = await GetMethodIdByName(cAttrTypeId, ".ctor", token); invokeParamsWriter.Write((byte)ElementType.Object); invokeParamsWriter.Write(objectId); - var retMethod = await InvokeMethod(sessionId, invokeParams.ToArray(), methodId, "methodRet", token); + var retMethod = await InvokeMethod(invokeParamsWriter.GetParameterBuffer(), methodId, "methodRet", token); DotnetObjectId.TryParse(retMethod?["value"]?["objectId"]?.Value(), out DotnetObjectId dotnetObjectId); - var displayAttrs = await GetObjectValues(sessionId, int.Parse(dotnetObjectId.Value), GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.ForDebuggerProxyAttribute, token); + var displayAttrs = await GetObjectValues(int.Parse(dotnetObjectId.Value), GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.ForDebuggerProxyAttribute, token); return displayAttrs; } } catch (Exception e) { - logger.LogDebug($"Could not evaluate DebuggerTypeProxyAttribute of type {await GetTypeName(sessionId, typeId, token)} - {e}"); + logger.LogDebug($"Could not evaluate DebuggerTypeProxyAttribute of type {await GetTypeName(typeId, token)} - {e}"); } return null; } - public async Task GetObjectValues(SessionId sessionId, int objectId, GetObjectCommandOptions getCommandType, CancellationToken token) + public async Task GetObjectValues(int objectId, GetObjectCommandOptions getCommandType, CancellationToken token) { - var typeId = await GetTypeIdFromObject(sessionId, objectId, true, token); + var typeId = await GetTypeIdFromObject(objectId, true, token); if (!getCommandType.HasFlag(GetObjectCommandOptions.ForDebuggerDisplayAttribute)) { - var debuggerProxy = await GetValuesFromDebuggerProxyAttribute(sessionId, objectId, typeId[0], token); + var debuggerProxy = await GetValuesFromDebuggerProxyAttribute(objectId, typeId[0], token); if (debuggerProxy != null) return debuggerProxy; } - var className = await GetTypeName(sessionId, typeId[0], token); + var className = await GetTypeName(typeId[0], token); JArray ret = new JArray(); - if (await IsDelegate(sessionId, objectId, token)) + if (await IsDelegate(objectId, token)) { - var description = await GetDelegateMethodDescription(sessionId, objectId, token); + var description = await GetDelegateMethodDescription(objectId, token); var obj = JObject.FromObject(new { value = new @@ -2356,14 +2337,13 @@ public async Task GetObjectValues(SessionId sessionId, int objectId, Get { if (!getCommandType.HasFlag(GetObjectCommandOptions.AccessorPropertiesOnly)) { - className = await GetTypeName(sessionId, typeId[i], token); - var fields = await GetTypeFields(sessionId, typeId[i], token); + className = await GetTypeName(typeId[i], token); + var fields = await GetTypeFields(typeId[i], token); if (getCommandType.HasFlag(GetObjectCommandOptions.ForDebuggerProxyAttribute)) fields = fields.Where(field => field.IsPublic).ToList(); JArray objectFields = new JArray(); - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(objectId); commandParamsWriter.Write(fields.Count); foreach (var field in fields) @@ -2371,31 +2351,31 @@ public async Task GetObjectValues(SessionId sessionId, int objectId, Get commandParamsWriter.Write(field.Id); } - var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefGetValues, commandParams, token); + using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdObject.RefGetValues, commandParamsWriter, token); foreach (var field in fields) { long initialPos = retDebuggerCmdReader.BaseStream.Position; int valtype = retDebuggerCmdReader.ReadByte(); retDebuggerCmdReader.BaseStream.Position = initialPos; - var fieldValue = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, field.Name, i == 0, field.TypeId, getCommandType.HasFlag(GetObjectCommandOptions.ForDebuggerDisplayAttribute), token); + var fieldValue = await CreateJObjectForVariableValue(retDebuggerCmdReader, field.Name, i == 0, field.TypeId, getCommandType.HasFlag(GetObjectCommandOptions.ForDebuggerDisplayAttribute), token); if (ret.Where(attribute => attribute["name"].Value().Equals(fieldValue["name"].Value())).Any()) { continue; } if (getCommandType.HasFlag(GetObjectCommandOptions.WithSetter)) { - var command_params_to_set = new MemoryStream(); - var command_params_writer_to_set = new MonoBinaryWriter(command_params_to_set); + var command_params_writer_to_set = new MonoBinaryWriter(); command_params_writer_to_set.Write(objectId); command_params_writer_to_set.Write(1); command_params_writer_to_set.Write(field.Id); + var (data, length) = command_params_writer_to_set.ToBase64(); fieldValue.Add("set", JObject.FromObject(new { commandSet = CommandSet.ObjectRef, command = CmdObject.RefSetValues, - buffer = Convert.ToBase64String(command_params_to_set.ToArray()), + buffer = data, valtype, - length = command_params_to_set.ToArray().Length + length = length })); } objectFields.Add(fieldValue); @@ -2404,10 +2384,9 @@ public async Task GetObjectValues(SessionId sessionId, int objectId, Get } if (!getCommandType.HasFlag(GetObjectCommandOptions.WithProperties)) return ret; - var command_params_obj = new MemoryStream(); - var commandParamsObjWriter = new MonoBinaryWriter(command_params_obj); + using var commandParamsObjWriter = new MonoBinaryWriter(); commandParamsObjWriter.WriteObj(new DotnetObjectId("object", $"{objectId}"), this); - var props = await CreateJArrayForProperties(sessionId, typeId[i], command_params_obj.ToArray(), ret, getCommandType.HasFlag(GetObjectCommandOptions.ForDebuggerProxyAttribute), $"dotnet:object:{objectId}", i == 0, token); + var props = await CreateJArrayForProperties(typeId[i], commandParamsObjWriter.GetParameterBuffer(), ret, getCommandType.HasFlag(GetObjectCommandOptions.ForDebuggerProxyAttribute), $"dotnet:object:{objectId}", i == 0, token); ret = new JArray(ret.Union(props)); // ownProperties @@ -2425,7 +2404,7 @@ public async Task GetObjectValues(SessionId sessionId, int objectId, Get List> allFields = new List>(); for (int i = 0; i < typeId.Count; i++) { - var fields = await GetTypeFields(sessionId, typeId[i], token); + var fields = await GetTypeFields(typeId[i], token); allFields.Add(fields); } foreach (var item in ret) @@ -2453,13 +2432,13 @@ public async Task GetObjectValues(SessionId sessionId, int objectId, Get return ret; } - public async Task GetObjectProxy(SessionId sessionId, int objectId, CancellationToken token) + public async Task GetObjectProxy(int objectId, CancellationToken token) { - var ret = await GetObjectValues(sessionId, objectId, GetObjectCommandOptions.WithSetter, token); - var typeIds = await GetTypeIdFromObject(sessionId, objectId, true, token); + var ret = await GetObjectValues(objectId, GetObjectCommandOptions.WithSetter, token); + var typeIds = await GetTypeIdFromObject(objectId, true, token); foreach (var typeId in typeIds) { - var retDebuggerCmdReader = await GetTypePropertiesReader(sessionId, typeId, token); + var retDebuggerCmdReader = await GetTypePropertiesReader(typeId, token); if (retDebuggerCmdReader == null) return null; @@ -2476,64 +2455,63 @@ public async Task GetObjectProxy(SessionId sessionId, int objectId, Canc { var attr = ret.Where(attribute => attribute["name"].Value().Equals(propertyNameStr)).First(); - var command_params_to_set = new MemoryStream(); - var command_params_writer_to_set = new MonoBinaryWriter(command_params_to_set); + using var command_params_writer_to_set = new MonoBinaryWriter(); command_params_writer_to_set.Write(setMethodId); command_params_writer_to_set.Write((byte)ElementType.Class); command_params_writer_to_set.Write(objectId); command_params_writer_to_set.Write(1); + var (data, length) = command_params_writer_to_set.ToBase64(); + if (attr["set"] != null) { attr["set"] = JObject.FromObject(new { commandSet = CommandSet.Vm, command = CmdVM.InvokeMethod, - buffer = Convert.ToBase64String(command_params_to_set.ToArray()), + buffer = data, valtype = attr["set"]["valtype"], - length = command_params_to_set.ToArray().Length + length = length }); } continue; } else { - var command_params_to_get = new MemoryStream(); - var command_params_writer_to_get = new MonoBinaryWriter(command_params_to_get); + var command_params_writer_to_get = new MonoBinaryWriter(); command_params_writer_to_get.Write(getMethodId); command_params_writer_to_get.Write((byte)ElementType.Class); command_params_writer_to_get.Write(objectId); command_params_writer_to_get.Write(0); + var (data, length) = command_params_writer_to_get.ToBase64(); ret.Add(JObject.FromObject(new { get = JObject.FromObject(new { commandSet = CommandSet.Vm, command = CmdVM.InvokeMethod, - buffer = Convert.ToBase64String(command_params_to_get.ToArray()), - length = command_params_to_get.ToArray().Length + buffer = data, + length = length }), name = propertyNameStr })); } - if (await MethodIsStatic(sessionId, getMethodId, token)) + if (await MethodIsStatic(getMethodId, token)) continue; } } return ret; } - public async Task SetVariableValue(SessionId sessionId, int thread_id, int frame_id, int varId, string newValue, CancellationToken token) + public async Task SetVariableValue(int thread_id, int frame_id, int varId, string newValue, CancellationToken token) { - var commandParams = new MemoryStream(); - var commandParamsWriter = new MonoBinaryWriter(commandParams); - MonoBinaryReader retDebuggerCmdReader = null; + using var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(thread_id); commandParamsWriter.Write(frame_id); commandParamsWriter.Write(1); commandParamsWriter.Write(varId); JArray locals = new JArray(); - retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetValues, commandParams, token); - int etype = retDebuggerCmdReader.ReadByte(); - retDebuggerCmdReader = await SendDebuggerAgentCommandWithParms(sessionId, CmdFrame.SetValues, commandParams, etype, newValue, token); - if (retDebuggerCmdReader.HasError) + using var getDebuggerCmdReader = await SendDebuggerAgentCommand(CmdFrame.GetValues, commandParamsWriter, token); + int etype = getDebuggerCmdReader.ReadByte(); + using var setDebuggerCmdReader = await SendDebuggerAgentCommandWithParms(CmdFrame.SetValues, commandParamsWriter.ToBase64(), etype, newValue, token); + if (setDebuggerCmdReader.HasError) return false; return true; }