diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index 6f1ec09317e0a..fb4eda76ca245 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -301,13 +301,13 @@ public DebugStore Store } } - public PerScopeCache GetCacheForScope(int scope_id) + public PerScopeCache GetCacheForScope(int scopeId) { - if (perScopeCaches.TryGetValue(scope_id, out PerScopeCache cache)) + if (perScopeCaches.TryGetValue(scopeId, out PerScopeCache cache)) return cache; cache = new PerScopeCache(); - perScopeCaches[scope_id] = cache; + perScopeCaches[scopeId] = cache; return cache; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs index 73de23d6fcc42..58374c43565c0 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs @@ -27,38 +27,54 @@ private class FindVariableNMethodCall : CSharpSyntaxWalker public List methodCall = new List(); public List memberAccesses = new List(); public List argValues = new List(); + public Dictionary memberAccessValues = new Dictionary(); + private int visitCount; + public bool hasMethodCalls; + public void VisitInternal(SyntaxNode node) + { + Visit(node); + visitCount++; + } public override void Visit(SyntaxNode node) { // TODO: PointerMemberAccessExpression - if (node is MemberAccessExpressionSyntax maes - && node.Kind() == SyntaxKind.SimpleMemberAccessExpression - && !(node.Parent is MemberAccessExpressionSyntax)) + if (visitCount == 0) { - memberAccesses.Add(maes); - } + if (node is MemberAccessExpressionSyntax maes + && node.Kind() == SyntaxKind.SimpleMemberAccessExpression + && !(node.Parent is MemberAccessExpressionSyntax) + && !(node.Parent is InvocationExpressionSyntax)) + { + memberAccesses.Add(maes); + } - if (node is IdentifierNameSyntax identifier - && !(identifier.Parent is MemberAccessExpressionSyntax) - && !identifiers.Any(x => x.Identifier.Text == identifier.Identifier.Text)) - { - identifiers.Add(identifier); + if (node is IdentifierNameSyntax identifier + && !(identifier.Parent is MemberAccessExpressionSyntax) + && !identifiers.Any(x => x.Identifier.Text == identifier.Identifier.Text)) + { + identifiers.Add(identifier); + } } if (node is InvocationExpressionSyntax) { - methodCall.Add(node as InvocationExpressionSyntax); - throw new Exception("Method Call is not implemented yet"); + if (visitCount == 1) + methodCall.Add(node as InvocationExpressionSyntax); + hasMethodCalls = true; } + if (node is AssignmentExpressionSyntax) throw new Exception("Assignment is not implemented yet"); base.Visit(node); } - public SyntaxTree ReplaceVars(SyntaxTree syntaxTree, IEnumerable ma_values, IEnumerable id_values) + public SyntaxTree ReplaceVars(SyntaxTree syntaxTree, IEnumerable ma_values, IEnumerable id_values, IEnumerable method_values) { - CompilationUnitSyntax root = syntaxTree.GetCompilationUnitRoot(); var memberAccessToParamName = new Dictionary(); + var methodCallToParamName = new Dictionary(); + + CompilationUnitSyntax root = syntaxTree.GetCompilationUnitRoot(); // 1. Replace all this.a occurrences with this_a_ABDE root = root.ReplaceNodes(memberAccesses, (maes, _) => @@ -77,25 +93,61 @@ public SyntaxTree ReplaceVars(SyntaxTree syntaxTree, IEnumerable ma_val return SyntaxFactory.IdentifierName(id_name); }); + // 1.1 Replace all this.a() occurrences with this_a_ABDE + root = root.ReplaceNodes(methodCall, (m, _) => + { + string iesStr = m.ToString(); + if (!methodCallToParamName.TryGetValue(iesStr, out string id_name)) + { + // Generate a random suffix + string suffix = Guid.NewGuid().ToString().Substring(0, 5); + string prefix = iesStr.Trim().Replace(".", "_").Replace("(", "_").Replace(")", "_"); + id_name = $"{prefix}_{suffix}"; + methodCallToParamName[iesStr] = id_name; + } + + return SyntaxFactory.IdentifierName(id_name); + }); + var paramsSet = new HashSet(); // 2. For every unique member ref, add a corresponding method param - foreach ((MemberAccessExpressionSyntax maes, JObject value) in memberAccesses.Zip(ma_values)) + if (ma_values != null) { - string node_str = maes.ToString(); - if (!memberAccessToParamName.TryGetValue(node_str, out string id_name)) + foreach ((MemberAccessExpressionSyntax maes, JObject value) in memberAccesses.Zip(ma_values)) { - throw new Exception($"BUG: Expected to find an id name for the member access string: {node_str}"); + string node_str = maes.ToString(); + if (!memberAccessToParamName.TryGetValue(node_str, out string id_name)) + { + throw new Exception($"BUG: Expected to find an id name for the member access string: {node_str}"); + } + memberAccessValues[id_name] = value; + root = UpdateWithNewMethodParam(root, id_name, value); } + } - root = UpdateWithNewMethodParam(root, id_name, value); + if (id_values != null) + { + foreach ((IdentifierNameSyntax idns, JObject value) in identifiers.Zip(id_values)) + { + root = UpdateWithNewMethodParam(root, idns.Identifier.Text, value); + } } - foreach ((IdentifierNameSyntax idns, JObject value) in identifiers.Zip(id_values)) + if (method_values != null) { - root = UpdateWithNewMethodParam(root, idns.Identifier.Text, value); + foreach ((InvocationExpressionSyntax ies, JObject value) in methodCall.Zip(method_values)) + { + string node_str = ies.ToString(); + if (!methodCallToParamName.TryGetValue(node_str, out string id_name)) + { + throw new Exception($"BUG: Expected to find an id name for the member access string: {node_str}"); + } + root = UpdateWithNewMethodParam(root, id_name, value); + } } + return syntaxTree.WithRootAndOptions(root, syntaxTree.Options); CompilationUnitSyntax UpdateWithNewMethodParam(CompilationUnitSyntax root, string id_name, JObject value) @@ -139,9 +191,9 @@ private object ConvertJSToCSharpType(JToken variable) case "boolean": return value?.Value(); case "object": - if (subType == "null") - return null; - break; + return null; + case "void": + return null; } throw new Exception($"Evaluate of this datatype {type} not implemented yet");//, "Unsupported"); } @@ -158,8 +210,11 @@ private string GetTypeFullName(JToken variable) { if (subType == "null") return variable["className"].Value(); - break; + else + return "object"; } + case "void": + return "object"; default: return value.GetType().FullName; } @@ -211,6 +266,20 @@ private static async Task> ResolveIdentifiers(IEnumerable> ResolveMethodCalls(IEnumerable methodCalls, Dictionary memberAccessValues, MemberReferenceResolver resolver, CancellationToken token) + { + var values = new List(); + foreach (InvocationExpressionSyntax methodCall in methodCalls) + { + JObject value = await resolver.Resolve(methodCall, memberAccessValues, token); + if (value == null) + throw new ReturnAsErrorException($"Failed to resolve member access for {methodCall}", "ReferenceError"); + + values.Add(value); + } + return values; + } + [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "Suppressing the warning until gets fixed, see https://github.com/dotnet/runtime/issues/51202")] internal static async Task CompileAndRunTheExpression(string expression, MemberReferenceResolver resolver, CancellationToken token) @@ -231,17 +300,17 @@ public static object Evaluate() throw new Exception($"BUG: Unable to evaluate {expression}, could not get expression from the syntax tree"); FindVariableNMethodCall findVarNMethodCall = new FindVariableNMethodCall(); - findVarNMethodCall.Visit(expressionTree); + findVarNMethodCall.VisitInternal(expressionTree); // this fails with `"a)"` // because the code becomes: return (a)); // and the returned expression from GetExpressionFromSyntaxTree is `a`! if (expressionTree.Kind() == SyntaxKind.IdentifierName || expressionTree.Kind() == SyntaxKind.ThisExpression) { - string var_name = expressionTree.ToString(); - JObject value = await resolver.Resolve(var_name, token); + string varName = expressionTree.ToString(); + JObject value = await resolver.Resolve(varName, token); if (value == null) - throw new ReturnAsErrorException($"Cannot find member named '{var_name}'.", "ReferenceError"); + throw new ReturnAsErrorException($"Cannot find member named '{varName}'.", "ReferenceError"); return value; } @@ -256,7 +325,19 @@ public static object Evaluate() IList identifierValues = await ResolveIdentifiers(findVarNMethodCall.identifiers, resolver, token); - syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, memberAccessValues, identifierValues); + syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, memberAccessValues, identifierValues, null); + + if (findVarNMethodCall.hasMethodCalls) + { + expressionTree = GetExpressionFromSyntaxTree(syntaxTree); + + findVarNMethodCall.VisitInternal(expressionTree); + + IList methodValues = await ResolveMethodCalls(findVarNMethodCall.methodCall, findVarNMethodCall.memberAccessValues, resolver, token); + + syntaxTree = findVarNMethodCall.ReplaceVars(syntaxTree, null, null, methodValues); + } + expressionTree = GetExpressionFromSyntaxTree(syntaxTree); if (expressionTree == null) throw new Exception($"BUG: Unable to evaluate {expression}, could not get expression from the syntax tree"); @@ -313,7 +394,7 @@ public static object Evaluate() private static object ConvertCSharpToJSType(object v, ITypeSymbol type) { if (v == null) - return new { type = "object", subtype = "null", className = type.ToString() }; + return new { type = "object", subtype = "null", className = type.ToString(), description = type.ToString() }; if (v is string s) { diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index c4e578a0a2c92..cd21ac6419094 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -9,6 +9,8 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.IO; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Collections.Generic; namespace Microsoft.WebAssembly.Diagnostics { @@ -22,14 +24,14 @@ internal class MemberReferenceResolver private ILogger logger; private bool locals_fetched; - public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId session_id, int scope_id, ILogger logger) + public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId sessionId, int scopeId, ILogger logger) { - sessionId = session_id; - scopeId = scope_id; + this.sessionId = sessionId; + this.scopeId = scopeId; this.proxy = proxy; this.ctx = ctx; this.logger = logger; - scopeCache = ctx.GetCacheForScope(scope_id); + scopeCache = ctx.GetCacheForScope(scopeId); } public async Task GetValueFromObject(JToken objRet, CancellationToken token) { @@ -37,7 +39,7 @@ public async Task GetValueFromObject(JToken objRet, CancellationToken t { if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value(), out DotnetObjectId objectId)) { - var exceptionObject = await proxy.sdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), true, false, false, true, token); + var exceptionObject = await proxy.SdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), true, false, false, true, 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(); @@ -51,10 +53,10 @@ public async Task GetValueFromObject(JToken objRet, CancellationToken t { if (DotnetObjectId.TryParse(objRet?["get"]?["objectIdValue"]?.Value(), out DotnetObjectId objectId)) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.WriteObj(objectId, proxy.sdbHelper); - var ret = await proxy.sdbHelper.InvokeMethod(sessionId, command_params.ToArray(), objRet["get"]["methodId"].Value(), objRet["name"].Value(), token); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.WriteObj(objectId, proxy.SdbHelper); + var ret = await proxy.SdbHelper.InvokeMethod(sessionId, commandParams.ToArray(), objRet["get"]["methodId"].Value(), objRet["name"].Value(), token); return await GetValueFromObject(ret, token); } @@ -62,12 +64,16 @@ public async Task GetValueFromObject(JToken objRet, CancellationToken t return null; } // Checks Locals, followed by `this` - public async Task Resolve(string var_name, CancellationToken token) + public async Task Resolve(string varName, CancellationToken token) { - string[] parts = var_name.Split("."); + //has method calls + if (varName.Contains('(')) + return null; + + string[] parts = varName.Split("."); JObject rootObject = null; - if (scopeCache.MemberReferences.TryGetValue(var_name, out JObject ret)) { + if (scopeCache.MemberReferences.TryGetValue(varName, out JObject ret)) { return ret; } foreach (string part in parts) @@ -81,8 +87,8 @@ public async Task Resolve(string var_name, CancellationToken token) return null; if (DotnetObjectId.TryParse(rootObject?["objectId"]?.Value(), out DotnetObjectId objectId)) { - var root_res_obj = await proxy.RuntimeGetPropertiesInternal(sessionId, objectId, null, token); - var objRet = root_res_obj.FirstOrDefault(objPropAttr => objPropAttr["name"].Value() == partTrimmed); + var rootResObj = await proxy.RuntimeGetPropertiesInternal(sessionId, objectId, null, token); + var objRet = rootResObj.FirstOrDefault(objPropAttr => objPropAttr["name"].Value() == partTrimmed); if (objRet == null) return null; @@ -109,8 +115,8 @@ public async Task Resolve(string var_name, CancellationToken token) } else if (DotnetObjectId.TryParse(objThis?["value"]?["objectId"]?.Value(), out DotnetObjectId objectId)) { - var root_res_obj = await proxy.RuntimeGetPropertiesInternal(sessionId, objectId, null, token); - var objRet = root_res_obj.FirstOrDefault(objPropAttr => objPropAttr["name"].Value() == partTrimmed); + var rootResObj = await proxy.RuntimeGetPropertiesInternal(sessionId, objectId, null, token); + var objRet = rootResObj.FirstOrDefault(objPropAttr => objPropAttr["name"].Value() == partTrimmed); if (objRet != null) { rootObject = await GetValueFromObject(objRet, token); @@ -122,9 +128,62 @@ public async Task Resolve(string var_name, CancellationToken token) } } } - scopeCache.MemberReferences[var_name] = rootObject; + scopeCache.MemberReferences[varName] = rootObject; return rootObject; } + public async Task Resolve(InvocationExpressionSyntax method, Dictionary memberAccessValues, CancellationToken token) + { + var methodName = ""; + try + { + JObject rootObject = null; + var expr = method.Expression; + if (expr is MemberAccessExpressionSyntax) + { + var memberAccessExpressionSyntax = expr as MemberAccessExpressionSyntax; + rootObject = await Resolve(memberAccessExpressionSyntax.Expression.ToString(), token); + methodName = memberAccessExpressionSyntax.Name.ToString(); + } + if (rootObject != null) + { + DotnetObjectId.TryParse(rootObject?["objectId"]?.Value(), out DotnetObjectId objectId); + var typeId = await proxy.SdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); + int methodId = await proxy.SdbHelper.GetMethodIdByName(sessionId, typeId[0], methodName, token); + if (methodId == 0) { + var typeName = await proxy.SdbHelper.GetTypeName(sessionId, typeId[0], token); + throw new Exception($"Method '{methodName}' not found in type '{typeName}'"); + } + var command_params_obj = new MemoryStream(); + var commandParamsObjWriter = new MonoBinaryWriter(command_params_obj); + commandParamsObjWriter.WriteObj(objectId, proxy.SdbHelper); + if (method.ArgumentList != null) + { + commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count); + foreach (var arg in method.ArgumentList.Arguments) + { + if (arg.Expression is LiteralExpressionSyntax) + { + if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, proxy.SdbHelper, token)) + return null; + } + if (arg.Expression is IdentifierNameSyntax) + { + var argParm = arg.Expression as IdentifierNameSyntax; + if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], proxy.SdbHelper, token)) + return null; + } + } + var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, command_params_obj.ToArray(), methodId, "methodRet", token); + return await GetValueFromObject(retMethod, token); + } + } + return null; + } + catch (Exception) + { + throw new Exception($"Unable to evaluate method '{methodName}'"); + } + } } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index f14bc1e16a99b..1872ec1d2a93e 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -18,7 +18,7 @@ namespace Microsoft.WebAssembly.Diagnostics { internal class MonoProxy : DevToolsProxy { - internal MonoSDBHelper sdbHelper; + internal MonoSDBHelper SdbHelper { get; } private IList urlSymbolServerList; private static HttpClient client = new HttpClient(); private HashSet sessions = new HashSet(); @@ -29,7 +29,7 @@ internal class MonoProxy : DevToolsProxy public MonoProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList) : base(loggerFactory) { this.urlSymbolServerList = urlSymbolServerList ?? new List(); - sdbHelper = new MonoSDBHelper(this); + SdbHelper = new MonoSDBHelper(this); } internal ExecutionContext GetContext(SessionId sessionId) @@ -449,7 +449,7 @@ protected override async Task AcceptCommand(MessageId id, string method, J } } else - await sdbHelper.EnableExceptions(id, state, token); + await SdbHelper.EnableExceptions(id, state, token); // Pass this on to JS too return false; } @@ -542,16 +542,16 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation switch (objectId.Scheme) { case "object": - args["details"] = await sdbHelper.GetObjectProxy(id, int.Parse(objectId.Value), token); + args["details"] = await SdbHelper.GetObjectProxy(id, int.Parse(objectId.Value), token); break; case "valuetype": - args["details"] = await sdbHelper.GetValueTypeProxy(id, int.Parse(objectId.Value), token); + args["details"] = await SdbHelper.GetValueTypeProxy(id, int.Parse(objectId.Value), token); break; case "pointer": - args["details"] = await sdbHelper.GetPointerContent(id, int.Parse(objectId.Value), token); + args["details"] = await SdbHelper.GetPointerContent(id, int.Parse(objectId.Value), token); break; case "array": - args["details"] = await sdbHelper.GetArrayValues(id, int.Parse(objectId.Value), token); + args["details"] = await SdbHelper.GetArrayValues(id, int.Parse(objectId.Value), token); break; case "cfo_res": { @@ -580,10 +580,10 @@ 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 ret_debugger_cmd = new MemoryStream(newBytes); - var ret_debugger_cmd_reader = new MonoBinaryReader(ret_debugger_cmd); - ret_debugger_cmd_reader.ReadByte(); //number of objects returned. - var obj = await sdbHelper.CreateJObjectForVariableValue(id, ret_debugger_cmd_reader, "ret", false, -1, token); + var retDebuggerCmd = new MemoryStream(newBytes); + var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + retDebuggerCmdReader.ReadByte(); //number of objects returned. + var obj = await SdbHelper.CreateJObjectForVariableValue(id, retDebuggerCmdReader, "ret", false, -1, token); /*JTokenType? res_value_type = res.Value?["result"]?["value"]?.Type;*/ res = Result.OkFromObject(new { result = obj["value"]}); SendResponse(id, res, token); @@ -606,7 +606,7 @@ private async Task OnSetVariableValue(MessageId id, int scopeId, string va 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 SdbHelper.SetVariableValue(id, ctx.ThreadId, scopeId, varToSetValue.Index, varValue["value"].Value(), token); if (res) SendResponse(id, Result.Ok(new JObject()), token); else @@ -635,13 +635,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 SdbHelper.GetValueTypeValues(id, int.Parse(objectId.Value), accessorPropertiesOnly, token); case "array": - return await sdbHelper.GetArrayValues(id, int.Parse(objectId.Value), token); + return await SdbHelper.GetArrayValues(id, int.Parse(objectId.Value), token); case "object": - return await sdbHelper.GetObjectValues(id, int.Parse(objectId.Value), true, false, accessorPropertiesOnly, ownProperties, token); + return await SdbHelper.GetObjectValues(id, int.Parse(objectId.Value), true, false, accessorPropertiesOnly, ownProperties, token); case "pointer": - return new JArray{await sdbHelper.GetPointerContent(id, int.Parse(objectId.Value), token)}; + return new JArray{await SdbHelper.GetPointerContent(id, int.Parse(objectId.Value), token)}; case "cfo_res": { Result res = await SendMonoCommand(id, MonoCommands.GetDetails(int.Parse(objectId.Value), args), token); @@ -690,34 +690,34 @@ private async Task EvaluateCondition(SessionId sessionId, ExecutionContext return false; } - private async Task ProcessEnC(SessionId sessionId, ExecutionContext context, MonoBinaryReader ret_debugger_cmd_reader, CancellationToken token) + private async Task ProcessEnC(SessionId sessionId, ExecutionContext context, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { - int moduleId = ret_debugger_cmd_reader.ReadInt32(); - int meta_size = ret_debugger_cmd_reader.ReadInt32(); - byte[] meta_buf = ret_debugger_cmd_reader.ReadBytes(meta_size); - int pdb_size = ret_debugger_cmd_reader.ReadInt32(); - byte[] pdb_buf = ret_debugger_cmd_reader.ReadBytes(pdb_size); + int moduleId = retDebuggerCmdReader.ReadInt32(); + int meta_size = retDebuggerCmdReader.ReadInt32(); + byte[] meta_buf = retDebuggerCmdReader.ReadBytes(meta_size); + int pdb_size = retDebuggerCmdReader.ReadInt32(); + byte[] pdb_buf = retDebuggerCmdReader.ReadBytes(pdb_size); - var assembly_name = await sdbHelper.GetAssemblyNameFromModule(sessionId, moduleId, token); + var assemblyName = await SdbHelper.GetAssemblyNameFromModule(sessionId, moduleId, token); DebugStore store = await LoadStore(sessionId, token); - AssemblyInfo asm = store.GetAssemblyByName(assembly_name); + AssemblyInfo asm = store.GetAssemblyByName(assemblyName); foreach (var method in store.EnC(sessionId, asm, meta_buf, pdb_buf)) await ResetBreakpoint(sessionId, method, token); return true; } - private async Task SendBreakpointsOfMethodUpdated(SessionId sessionId, ExecutionContext context, MonoBinaryReader ret_debugger_cmd_reader, CancellationToken token) + private async Task SendBreakpointsOfMethodUpdated(SessionId sessionId, ExecutionContext context, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { - var method_id = ret_debugger_cmd_reader.ReadInt32(); - var method_token = await sdbHelper.GetMethodToken(sessionId, method_id, token); - var assembly_id = await sdbHelper.GetAssemblyIdFromMethod(sessionId, method_id, token); - var assembly_name = await sdbHelper.GetAssemblyName(sessionId, assembly_id, token); - var method_name = await sdbHelper.GetMethodName(sessionId, method_id, token); + var method_id = retDebuggerCmdReader.ReadInt32(); + var method_token = await SdbHelper.GetMethodToken(sessionId, method_id, token); + var assembly_id = await SdbHelper.GetAssemblyIdFromMethod(sessionId, method_id, token); + var assembly_name = await SdbHelper.GetAssemblyName(sessionId, assembly_id, token); + var method_name = await SdbHelper.GetMethodName(sessionId, method_id, token); DebugStore store = await LoadStore(sessionId, token); AssemblyInfo asm = store.GetAssemblyByName(assembly_name); if (asm == null) { - assembly_name = await sdbHelper.GetAssemblyNameFull(sessionId, assembly_id, token); + assembly_name = await SdbHelper.GetAssemblyNameFull(sessionId, assembly_id, token); asm = store.GetAssemblyByName(assembly_name); if (asm == null) { @@ -743,28 +743,28 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con { var callFrames = new List(); var frames = new List(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(thread_id); - command_params_writer.Write(0); - command_params_writer.Write(-1); - var ret_debugger_cmd_reader = await sdbHelper.SendDebuggerAgentCommand(sessionId, CmdThread.GetFrameInfo, command_params, token); - var frame_count = ret_debugger_cmd_reader.ReadInt32(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(thread_id); + commandParamsWriter.Write(0); + commandParamsWriter.Write(-1); + var retDebuggerCmdReader = await SdbHelper.SendDebuggerAgentCommand(sessionId, CmdThread.GetFrameInfo, commandParams, token); + var frame_count = retDebuggerCmdReader.ReadInt32(); //Console.WriteLine("frame_count - " + frame_count); for (int j = 0; j < frame_count; j++) { - var frame_id = ret_debugger_cmd_reader.ReadInt32(); - var method_id = ret_debugger_cmd_reader.ReadInt32(); - var il_pos = ret_debugger_cmd_reader.ReadInt32(); - var flags = ret_debugger_cmd_reader.ReadByte(); - var method_token = await sdbHelper.GetMethodToken(sessionId, method_id, token); - var assembly_id = await sdbHelper.GetAssemblyIdFromMethod(sessionId, method_id, token); - var assembly_name = await sdbHelper.GetAssemblyName(sessionId, assembly_id, token); - var method_name = await sdbHelper.GetMethodName(sessionId, method_id, token); + var frame_id = retDebuggerCmdReader.ReadInt32(); + var methodId = retDebuggerCmdReader.ReadInt32(); + var il_pos = retDebuggerCmdReader.ReadInt32(); + var flags = retDebuggerCmdReader.ReadByte(); + var method_token = await SdbHelper.GetMethodToken(sessionId, methodId, token); + var assembly_id = await SdbHelper.GetAssemblyIdFromMethod(sessionId, methodId, token); + var assembly_name = await SdbHelper.GetAssemblyName(sessionId, assembly_id, token); + var method_name = await SdbHelper.GetMethodName(sessionId, methodId, token); DebugStore store = await LoadStore(sessionId, token); AssemblyInfo asm = store.GetAssemblyByName(assembly_name); if (asm == null) { - assembly_name = await sdbHelper.GetAssemblyNameFull(sessionId, assembly_id, token); //maybe is a lazy loaded assembly + assembly_name = await SdbHelper.GetAssemblyNameFull(sessionId, assembly_id, token); //maybe is a lazy loaded assembly asm = store.GetAssemblyByName(assembly_name); if (asm == null) { @@ -794,7 +794,7 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con continue; } - method.DebuggerId = method_id; + method.DebuggerId = methodId; SourceLocation location = method?.GetLocationByIl(il_pos); @@ -881,43 +881,43 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec ExecutionContext context = GetContext(sessionId); byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); - var ret_debugger_cmd = new MemoryStream(newBytes); - var ret_debugger_cmd_reader = new MonoBinaryReader(ret_debugger_cmd); - ret_debugger_cmd_reader.ReadBytes(11); //skip HEADER_LEN - ret_debugger_cmd_reader.ReadByte(); //suspend_policy - var number_of_events = ret_debugger_cmd_reader.ReadInt32(); //number of events -> should be always one + var retDebuggerCmd = new MemoryStream(newBytes); + var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + retDebuggerCmdReader.ReadBytes(11); //skip HEADER_LEN + retDebuggerCmdReader.ReadByte(); //suspend_policy + var number_of_events = retDebuggerCmdReader.ReadInt32(); //number of events -> should be always one for (int i = 0 ; i < number_of_events; i++) { - var event_kind = (EventKind)ret_debugger_cmd_reader.ReadByte(); //event kind - var request_id = ret_debugger_cmd_reader.ReadInt32(); //request id + 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); - int thread_id = ret_debugger_cmd_reader.ReadInt32(); + await SdbHelper.ClearSingleStep(sessionId, request_id, token); + int thread_id = retDebuggerCmdReader.ReadInt32(); switch (event_kind) { case EventKind.MethodUpdate: { - var ret = await SendBreakpointsOfMethodUpdated(sessionId, context, ret_debugger_cmd_reader, token); + var ret = await SendBreakpointsOfMethodUpdated(sessionId, context, retDebuggerCmdReader, token); await SendCommand(sessionId, "Debugger.resume", new JObject(), token); return ret; } case EventKind.EnC: { - var ret = await ProcessEnC(sessionId, context, ret_debugger_cmd_reader, token); + var ret = await ProcessEnC(sessionId, context, retDebuggerCmdReader, token); await SendCommand(sessionId, "Debugger.resume", new JObject(), token); return ret; } case EventKind.Exception: { string reason = "exception"; - int object_id = ret_debugger_cmd_reader.ReadInt32(); - var caught = ret_debugger_cmd_reader.ReadByte(); - var exceptionObject = await sdbHelper.GetObjectValues(sessionId, object_id, true, false, false, true, token); + int object_id = retDebuggerCmdReader.ReadInt32(); + var caught = retDebuggerCmdReader.ReadByte(); + var exceptionObject = await SdbHelper.GetObjectValues(sessionId, object_id, true, false, false, true, 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 SdbHelper.GetClassNameFromObject(sessionId, object_id, token), uncaught = caught == 0, description = exceptionObjectMessage["value"]["value"].Value(), objectId = $"dotnet:object:{object_id}" @@ -932,9 +932,9 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec { Breakpoint bp = context.BreakpointRequests.Values.SelectMany(v => v.Locations).FirstOrDefault(b => b.RemoteId == request_id); string reason = "other";//other means breakpoint - int method_id = 0; + int methodId = 0; if (event_kind != EventKind.UserBreak) - method_id = ret_debugger_cmd_reader.ReadInt32(); + methodId = retDebuggerCmdReader.ReadInt32(); var ret = await SendCallStack(sessionId, context, reason, thread_id, bp, null, args?["callFrames"]?.Values(), token); return ret; } @@ -1018,7 +1018,7 @@ private async Task OnResume(MessageId msg_id, CancellationToken token) } //discard managed frames - sdbHelper.ClearCache(); + SdbHelper.ClearCache(); GetContext(msg_id).ClearState(); } @@ -1031,9 +1031,9 @@ private async Task Step(MessageId msg_id, StepKind kind, CancellationToken if (context.CallStack.Count <= 1 && kind == StepKind.Out) return false; - var step = await sdbHelper.Step(msg_id, context.ThreadId, kind, token); + var step = await SdbHelper.Step(msg_id, context.ThreadId, kind, token); if (step == false) { - sdbHelper.ClearCache(); + SdbHelper.ClearCache(); context.ClearState(); await SendCommand(msg_id, "Debugger.stepOut", new JObject(), token); return false; @@ -1110,7 +1110,7 @@ private async Task OnAssemblyLoadedJSEvent(SessionId sessionId, JObject ev } } - private async Task OnEvaluateOnCallFrame(MessageId msg_id, int scope_id, string expression, CancellationToken token) + private async Task OnEvaluateOnCallFrame(MessageId msg_id, int scopeId, string expression, CancellationToken token) { try { @@ -1118,7 +1118,7 @@ private async Task OnEvaluateOnCallFrame(MessageId msg_id, int scope_id, s if (context.CallStack == null) return false; - var resolver = new MemberReferenceResolver(this, context, msg_id, scope_id, logger); + var resolver = new MemberReferenceResolver(this, context, msg_id, scopeId, logger); JObject retValue = await resolver.Resolve(expression, token); if (retValue == null) @@ -1151,24 +1151,24 @@ private async Task OnEvaluateOnCallFrame(MessageId msg_id, int scope_id, s return true; } - internal async Task GetScopeProperties(SessionId msg_id, int scope_id, CancellationToken token) + internal async Task GetScopeProperties(SessionId msg_id, int scopeId, CancellationToken token) { try { ExecutionContext ctx = GetContext(msg_id); - Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scope_id); + Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId); if (scope == null) - return Result.Err(JObject.FromObject(new { message = $"Could not find scope with id #{scope_id}" })); + return Result.Err(JObject.FromObject(new { message = $"Could not find scope with id #{scopeId}" })); - VarInfo[] var_ids = scope.Method.GetLiveVarsAt(scope.Location.CliLocation.Offset); + VarInfo[] varIds = scope.Method.GetLiveVarsAt(scope.Location.CliLocation.Offset); - var values = await sdbHelper.StackFrameGetValues(msg_id, scope.Method, ctx.ThreadId, scope_id, var_ids, token); + var values = await SdbHelper.StackFrameGetValues(msg_id, scope.Method, ctx.ThreadId, scopeId, varIds, token); if (values != null) { if (values == null || values.Count == 0) return Result.OkFromObject(new { result = Array.Empty() }); - PerScopeCache frameCache = ctx.GetCacheForScope(scope_id); + PerScopeCache frameCache = ctx.GetCacheForScope(scopeId); foreach (JObject value in values) { frameCache.Locals[value["name"]?.Value()] = value; @@ -1191,9 +1191,9 @@ private async Task SetMonoBreakpoint(SessionId sessionId, string req int method_token = bp.Location.CliLocation.Method.Token; int il_offset = bp.Location.CliLocation.Offset; - var assembly_id = await sdbHelper.GetAssemblyId(sessionId, asm_name, token); - var method_id = await sdbHelper.GetMethodIdByToken(sessionId, assembly_id, method_token, token); - var breakpoint_id = await sdbHelper.SetBreakpoint(sessionId, method_id, il_offset, token); + 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); if (breakpoint_id > 0) { @@ -1258,22 +1258,22 @@ private async Task RuntimeReady(SessionId sessionId, CancellationTok if (Interlocked.CompareExchange(ref context.ready, new TaskCompletionSource(), null) != null) return await context.ready.Task; - var command_params = new MemoryStream(); - var ret_debugger_cmd_reader = await sdbHelper.SendDebuggerAgentCommand(sessionId, CmdEventRequest.ClearAllBreakpoints, command_params, token); - if (ret_debugger_cmd_reader == null) + var commandParams = new MemoryStream(); + var retDebuggerCmdReader = await SdbHelper.SendDebuggerAgentCommand(sessionId, CmdEventRequest.ClearAllBreakpoints, commandParams, token); + if (retDebuggerCmdReader == null) { Log("verbose", $"Failed to clear breakpoints"); } if (context.PauseOnCaught && context.PauseOnUncaught) - await sdbHelper.EnableExceptions(sessionId, "all", token); + await SdbHelper.EnableExceptions(sessionId, "all", token); else if (context.PauseOnUncaught) - await sdbHelper.EnableExceptions(sessionId, "uncaught", token); + await SdbHelper.EnableExceptions(sessionId, "uncaught", 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 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); DebugStore store = await LoadStore(sessionId, token); @@ -1306,7 +1306,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 SdbHelper.RemoveBreakpoint(msg_id, bp.RemoteId, token); if (breakpoint_removed) { bp.RemoteId = -1; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 42ad54e6e2c61..d12533c1e9ffb 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -14,6 +14,8 @@ using Newtonsoft.Json.Linq; using System.Net.Http; using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp; namespace Microsoft.WebAssembly.Diagnostics { @@ -462,7 +464,7 @@ public override void Write(int val) Array.Reverse(bytes, 0, bytes.Length); Write(bytes); } - public void WriteObj(DotnetObjectId objectId, MonoSDBHelper sdbHelper) + public void WriteObj(DotnetObjectId objectId, MonoSDBHelper SdbHelper) { if (objectId.Scheme == "object") { @@ -471,9 +473,90 @@ public void WriteObj(DotnetObjectId objectId, MonoSDBHelper sdbHelper) } if (objectId.Scheme == "valuetype") { - Write(sdbHelper.valueTypes[int.Parse(objectId.Value)].valueTypeBuffer); + Write(SdbHelper.valueTypes[int.Parse(objectId.Value)].valueTypeBuffer); } } + public async Task WriteConst(SessionId sessionId, LiteralExpressionSyntax constValue, MonoSDBHelper SdbHelper, CancellationToken token) + { + switch (constValue.Kind()) + { + case SyntaxKind.NumericLiteralExpression: + { + Write((byte)ElementType.I4); + Write((int)constValue.Token.Value); + return true; + } + case SyntaxKind.StringLiteralExpression: + { + int stringId = await SdbHelper.CreateString(sessionId, (string)constValue.Token.Value, token); + Write((byte)ElementType.String); + Write((int)stringId); + return true; + } + case SyntaxKind.TrueLiteralExpression: + { + Write((byte)ElementType.Boolean); + Write((int)1); + return true; + } + case SyntaxKind.FalseLiteralExpression: + { + Write((byte)ElementType.Boolean); + Write((int)0); + return true; + } + case SyntaxKind.NullLiteralExpression: + { + Write((byte)ValueTypeId.Null); + Write((byte)0); //not used + Write((int)0); //not used + return true; + } + case SyntaxKind.CharacterLiteralExpression: + { + Write((byte)ElementType.Char); + Write((int)(char)constValue.Token.Value); + return true; + } + } + return false; + } + + public async Task WriteJsonValue(SessionId sessionId, JObject objValue, MonoSDBHelper SdbHelper, CancellationToken token) + { + switch (objValue["type"].Value()) + { + case "number": + { + Write((byte)ElementType.I4); + Write(objValue["value"].Value()); + return true; + } + case "string": + { + int stringId = await SdbHelper.CreateString(sessionId, objValue["value"].Value(), token); + Write((byte)ElementType.String); + Write((int)stringId); + return true; + } + case "boolean": + { + Write((byte)ElementType.Boolean); + if (objValue["value"].Value()) + Write((int)1); + else + Write((int)0); + return true; + } + case "object": + { + DotnetObjectId.TryParse(objValue["objectId"]?.Value(), out DotnetObjectId objectId); + WriteObj(objectId, SdbHelper); + return true; + } + } + return false; + } } internal class FieldTypeClass { @@ -545,24 +628,24 @@ public void ClearCache() public async Task SetProtocolVersion(SessionId sessionId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(MAJOR_VERSION); - command_params_writer.Write(MINOR_VERSION); - command_params_writer.Write((byte)0); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(MAJOR_VERSION); + commandParamsWriter.Write(MINOR_VERSION); + commandParamsWriter.Write((byte)0); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdVM.SetProtocolVersion, command_params, token); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.SetProtocolVersion, commandParams, token); return true; } - public async Task EnableReceiveRequests(SessionId sessionId, EventKind event_kind, CancellationToken token) + public async Task EnableReceiveRequests(SessionId sessionId, EventKind eventKind, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((byte)event_kind); - command_params_writer.Write((byte)SuspendPolicy.None); - command_params_writer.Write((byte)0); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, command_params, token); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((byte)eventKind); + commandParamsWriter.Write((byte)SuspendPolicy.None); + commandParamsWriter.Write((byte)0); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); return true; } @@ -573,9 +656,9 @@ internal async Task SendDebuggerAgentCommandInternal(SessionId throw new Exception($"SendDebuggerAgentCommand Error - {(CommandSet)command_set} - {command}"); } byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); - var ret_debugger_cmd = new MemoryStream(newBytes); - var ret_debugger_cmd_reader = new MonoBinaryReader(ret_debugger_cmd); - return ret_debugger_cmd_reader; + var retDebuggerCmd = new MemoryStream(newBytes); + var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + return retDebuggerCmdReader; } internal CommandSet GetCommandSetForCommand(T command) => @@ -611,49 +694,61 @@ internal async Task SendDebuggerAgentCommandWithParmsInternal( throw new Exception("SendDebuggerAgentCommandWithParms Error"); } byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); - var ret_debugger_cmd = new MemoryStream(newBytes); - var ret_debugger_cmd_reader = new MonoBinaryReader(ret_debugger_cmd); - return ret_debugger_cmd_reader; + var retDebuggerCmd = new MemoryStream(newBytes); + var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + return retDebuggerCmdReader; } - public async Task GetMethodToken(SessionId sessionId, int method_id, CancellationToken token) + public async Task CreateString(SessionId sessionId, string value, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(method_id); + 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); + commandParamsWriter.WriteString(value); + retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAppDomain.CreateString, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); + } - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.Token, command_params, token); - return ret_debugger_cmd_reader.ReadInt32() & 0xffffff; //token + public async Task GetMethodToken(SessionId sessionId, int methodId, CancellationToken token) + { + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.Token, commandParams, token); + return retDebuggerCmdReader.ReadInt32() & 0xffffff; //token } public async Task GetMethodIdByToken(SessionId sessionId, int assembly_id, int method_token, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(assembly_id); - command_params_writer.Write(method_token | (int)TokenType.MdtMethodDef); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetMethodFromToken, command_params, token); - return ret_debugger_cmd_reader.ReadInt32(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(assembly_id); + commandParamsWriter.Write(method_token | (int)TokenType.MdtMethodDef); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetMethodFromToken, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); } - public async Task GetAssemblyIdFromMethod(SessionId sessionId, int method_id, CancellationToken token) + public async Task GetAssemblyIdFromMethod(SessionId sessionId, int methodId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(method_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.Assembly, command_params, token); - return ret_debugger_cmd_reader.ReadInt32(); //assembly_id + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.Assembly, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); //assembly_id } public async Task GetAssemblyId(SessionId sessionId, string asm_name, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.WriteString(asm_name); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.WriteString(asm_name); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdVM.GetAssemblyByName, command_params, token); - return ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.GetAssemblyByName, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); } public async Task GetAssemblyNameFromModule(SessionId sessionId, int moduleId, CancellationToken token) @@ -669,90 +764,90 @@ public async Task GetAssemblyNameFromModule(SessionId sessionId, int mod public async Task GetAssemblyName(SessionId sessionId, int assembly_id, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(assembly_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(assembly_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetLocation, command_params, token); - return ret_debugger_cmd_reader.ReadString(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetLocation, commandParams, token); + return retDebuggerCmdReader.ReadString(); } public async Task GetAssemblyNameFull(SessionId sessionId, int assembly_id, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(assembly_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(assembly_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetName, command_params, token); - var name = ret_debugger_cmd_reader.ReadString(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetName, commandParams, token); + var name = retDebuggerCmdReader.ReadString(); return name.Remove(name.IndexOf(",")) + ".dll"; } - public async Task GetMethodName(SessionId sessionId, int method_id, CancellationToken token) + public async Task GetMethodName(SessionId sessionId, int methodId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(method_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetNameFull, command_params, token); - var methodName = ret_debugger_cmd_reader.ReadString(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetNameFull, commandParams, token); + var methodName = retDebuggerCmdReader.ReadString(); return methodName.Substring(methodName.IndexOf(":")+1); } - public async Task MethodIsStatic(SessionId sessionId, int method_id, CancellationToken token) + public async Task MethodIsStatic(SessionId sessionId, int methodId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(method_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetInfo, command_params, token); - var flags = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetInfo, commandParams, token); + var flags = retDebuggerCmdReader.ReadInt32(); return (flags & 0x0010) > 0; //check method is static } - public async Task GetParamCount(SessionId sessionId, int method_id, CancellationToken token) + public async Task GetParamCount(SessionId sessionId, int methodId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(method_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, command_params, token); - ret_debugger_cmd_reader.ReadInt32(); - int param_count = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, commandParams, token); + retDebuggerCmdReader.ReadInt32(); + int param_count = retDebuggerCmdReader.ReadInt32(); return param_count; } - public async Task GetReturnType(SessionId sessionId, int method_id, CancellationToken token) + public async Task GetReturnType(SessionId sessionId, int methodId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(method_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, command_params, token); - ret_debugger_cmd_reader.ReadInt32(); - ret_debugger_cmd_reader.ReadInt32(); - ret_debugger_cmd_reader.ReadInt32(); - var retType = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, commandParams, token); + retDebuggerCmdReader.ReadInt32(); + retDebuggerCmdReader.ReadInt32(); + retDebuggerCmdReader.ReadInt32(); + var retType = retDebuggerCmdReader.ReadInt32(); var ret = await GetTypeName(sessionId, retType, token); return ret; } - public async Task GetParameters(SessionId sessionId, int method_id, CancellationToken token) + public async Task GetParameters(SessionId sessionId, int methodId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(method_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, command_params, token); - ret_debugger_cmd_reader.ReadInt32(); - var paramCount = ret_debugger_cmd_reader.ReadInt32(); - ret_debugger_cmd_reader.ReadInt32(); - var retType = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetParamInfo, commandParams, token); + retDebuggerCmdReader.ReadInt32(); + var paramCount = retDebuggerCmdReader.ReadInt32(); + retDebuggerCmdReader.ReadInt32(); + var retType = retDebuggerCmdReader.ReadInt32(); var parameters = "("; for (int i = 0 ; i < paramCount; i++) { - var paramType = ret_debugger_cmd_reader.ReadInt32(); + var paramType = retDebuggerCmdReader.ReadInt32(); parameters += await GetTypeName(sessionId, paramType, token); parameters = parameters.Replace("System.Func", "Func"); if (i + 1 < paramCount) @@ -762,50 +857,50 @@ public async Task GetParameters(SessionId sessionId, int method_id, Canc return parameters; } - public async Task SetBreakpoint(SessionId sessionId, int method_id, long il_offset, CancellationToken token) + public async Task SetBreakpoint(SessionId sessionId, int methodId, long il_offset, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((byte)EventKind.Breakpoint); - command_params_writer.Write((byte)SuspendPolicy.None); - command_params_writer.Write((byte)1); - command_params_writer.Write((byte)ModifierKind.LocationOnly); - command_params_writer.Write(method_id); - command_params_writer.WriteLong(il_offset); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, command_params, token); - return ret_debugger_cmd_reader.ReadInt32(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((byte)EventKind.Breakpoint); + commandParamsWriter.Write((byte)SuspendPolicy.None); + commandParamsWriter.Write((byte)1); + commandParamsWriter.Write((byte)ModifierKind.LocationOnly); + commandParamsWriter.Write(methodId); + commandParamsWriter.WriteLong(il_offset); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); } public async Task RemoveBreakpoint(SessionId sessionId, int breakpoint_id, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((byte)EventKind.Breakpoint); - command_params_writer.Write((int) breakpoint_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((byte)EventKind.Breakpoint); + commandParamsWriter.Write((int) breakpoint_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Clear, command_params, token); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Clear, commandParams, token); - if (ret_debugger_cmd_reader != null) + if (retDebuggerCmdReader != null) return true; return false; } public async Task Step(SessionId sessionId, int thread_id, StepKind kind, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((byte)EventKind.Step); - command_params_writer.Write((byte)SuspendPolicy.None); - command_params_writer.Write((byte)1); - command_params_writer.Write((byte)ModifierKind.Step); - command_params_writer.Write(thread_id); - command_params_writer.Write((int)0); - command_params_writer.Write((int)kind); - command_params_writer.Write((int)(StepFilter.StaticCtor | StepFilter.DebuggerHidden)); //filter - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, command_params, token); - if (ret_debugger_cmd_reader == null) + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((byte)EventKind.Step); + commandParamsWriter.Write((byte)SuspendPolicy.None); + commandParamsWriter.Write((byte)1); + commandParamsWriter.Write((byte)ModifierKind.Step); + commandParamsWriter.Write(thread_id); + commandParamsWriter.Write((int)0); + commandParamsWriter.Write((int)kind); + commandParamsWriter.Write((int)(StepFilter.StaticCtor | StepFilter.DebuggerHidden)); //filter + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, commandParams, token); + if (retDebuggerCmdReader == null) return false; - var isBPOnManagedCode = ret_debugger_cmd_reader.ReadInt32(); + var isBPOnManagedCode = retDebuggerCmdReader.ReadInt32(); if (isBPOnManagedCode == 0) return false; return true; @@ -813,14 +908,14 @@ public async Task Step(SessionId sessionId, int thread_id, StepKind kind, public async Task ClearSingleStep(SessionId sessionId, int req_id, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((byte)EventKind.Step); - command_params_writer.Write((int) req_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((byte)EventKind.Step); + commandParamsWriter.Write((int) req_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Clear, command_params, token); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Clear, commandParams, token); - if (ret_debugger_cmd_reader != null) + if (retDebuggerCmdReader != null) return true; return false; } @@ -828,19 +923,19 @@ public async Task ClearSingleStep(SessionId sessionId, int req_id, Cancell public async Task> GetTypeFields(SessionId sessionId, int type_id, CancellationToken token) { var ret = new List(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(type_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(type_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetFields, command_params, token); - var nFields = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetFields, commandParams, token); + var nFields = retDebuggerCmdReader.ReadInt32(); for (int i = 0 ; i < nFields; i++) { - int fieldId = ret_debugger_cmd_reader.ReadInt32(); //fieldId - string fieldNameStr = ret_debugger_cmd_reader.ReadString(); - int typeId = ret_debugger_cmd_reader.ReadInt32(); //typeId - ret_debugger_cmd_reader.ReadInt32(); //attrs + int fieldId = retDebuggerCmdReader.ReadInt32(); //fieldId + string fieldNameStr = retDebuggerCmdReader.ReadString(); + int typeId = retDebuggerCmdReader.ReadInt32(); //typeId + retDebuggerCmdReader.ReadInt32(); //attrs if (fieldNameStr.Contains("k__BackingField")) { fieldNameStr = fieldNameStr.Replace("k__BackingField", ""); @@ -864,17 +959,17 @@ public string ReplaceCommonClassNames(string className) } public async Task GetTypeName(SessionId sessionId, int type_id, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(type_id); - command_params_writer.Write((int) MonoTypeNameFormat.FormatReflection); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetInfo, command_params, token); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(type_id); + commandParamsWriter.Write((int) MonoTypeNameFormat.FormatReflection); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetInfo, commandParams, token); - ret_debugger_cmd_reader.ReadString(); + retDebuggerCmdReader.ReadString(); - ret_debugger_cmd_reader.ReadString(); + retDebuggerCmdReader.ReadString(); - string className = ret_debugger_cmd_reader.ReadString(); + string className = retDebuggerCmdReader.ReadString(); className = className.Replace("+", "."); className = Regex.Replace(className, @"`\d+", ""); @@ -889,47 +984,47 @@ public async Task GetTypeName(SessionId sessionId, int type_id, Cancella public async Task GetStringValue(SessionId sessionId, int string_id, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(string_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(string_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdString.GetValue, command_params, token); - var isUtf16 = ret_debugger_cmd_reader.ReadByte(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdString.GetValue, commandParams, token); + var isUtf16 = retDebuggerCmdReader.ReadByte(); if (isUtf16 == 0) { - return ret_debugger_cmd_reader.ReadString(); + return retDebuggerCmdReader.ReadString(); } return null; } public async Task GetArrayLength(SessionId sessionId, int object_id, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(object_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetLength, command_params, token); - var length = ret_debugger_cmd_reader.ReadInt32(); - length = ret_debugger_cmd_reader.ReadInt32(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(object_id); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetLength, commandParams, token); + var length = retDebuggerCmdReader.ReadInt32(); + length = retDebuggerCmdReader.ReadInt32(); return length; } public async Task> GetTypeIdFromObject(SessionId sessionId, int object_id, bool withParents, CancellationToken token) { List ret = new List(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(object_id); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(object_id); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefGetType, command_params, token); - var type_id = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefGetType, commandParams, token); + var type_id = retDebuggerCmdReader.ReadInt32(); ret.Add(type_id); if (withParents) { - command_params = new MemoryStream(); - command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(type_id); - ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetParents, command_params, token); - var parentsCount = ret_debugger_cmd_reader.ReadInt32(); + commandParams = new MemoryStream(); + commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(type_id); + retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetParents, commandParams, token); + var parentsCount = retDebuggerCmdReader.ReadInt32(); for (int i = 0 ; i < parentsCount; i++) { - ret.Add(ret_debugger_cmd_reader.ReadInt32()); + ret.Add(retDebuggerCmdReader.ReadInt32()); } } return ret; @@ -944,82 +1039,82 @@ public async Task GetClassNameFromObject(SessionId sessionId, int object public async Task GetMethodIdByName(SessionId sessionId, int type_id, string method_name, CancellationToken token) { var ret = new List(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((int)type_id); - command_params_writer.WriteString(method_name); - command_params_writer.Write((int)(0x10 | 4)); //instance methods - command_params_writer.Write((int)1); //case sensitive - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetMethodsByNameFlags, command_params, token); - var nMethods = ret_debugger_cmd_reader.ReadInt32(); - return ret_debugger_cmd_reader.ReadInt32(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((int)type_id); + commandParamsWriter.WriteString(method_name); + commandParamsWriter.Write((int)(0x10 | 4)); //instance methods + commandParamsWriter.Write((int)1); //case sensitive + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetMethodsByNameFlags, commandParams, token); + var nMethods = retDebuggerCmdReader.ReadInt32(); + return retDebuggerCmdReader.ReadInt32(); } public async Task IsDelegate(SessionId sessionId, int objectId, CancellationToken token) { var ret = new List(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((int)objectId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefIsDelegate, command_params, token); - return ret_debugger_cmd_reader.ReadByte() == 1; + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((int)objectId); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefIsDelegate, commandParams, token); + return retDebuggerCmdReader.ReadByte() == 1; } public async Task GetDelegateMethod(SessionId sessionId, int objectId, CancellationToken token) { var ret = new List(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((int)objectId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefDelegateGetMethod, command_params, token); - return ret_debugger_cmd_reader.ReadInt32(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((int)objectId); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefDelegateGetMethod, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); } public async Task GetDelegateMethodDescription(SessionId sessionId, int objectId, CancellationToken token) { var methodId = await GetDelegateMethod(sessionId, objectId, token); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(methodId); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); //Console.WriteLine("methodId - " + methodId); if (methodId == 0) return ""; - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetName, command_params, token); - var methodName = ret_debugger_cmd_reader.ReadString(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.GetName, commandParams, token); + var methodName = retDebuggerCmdReader.ReadString(); var returnType = await GetReturnType(sessionId, methodId, token); var parameters = await GetParameters(sessionId, methodId, token); return $"{returnType} {methodName} {parameters}"; } - public async Task InvokeMethod(SessionId sessionId, byte[] valueTypeBuffer, int method_id, string varName, CancellationToken token) + public async Task InvokeMethod(SessionId sessionId, byte[] valueTypeBuffer, int methodId, string varName, CancellationToken token) { MemoryStream parms = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(parms); - command_params_writer.Write(method_id); - command_params_writer.Write(valueTypeBuffer); - command_params_writer.Write(0); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdVM.InvokeMethod, parms, token); - ret_debugger_cmd_reader.ReadByte(); //number of objects returned. - return await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, varName, false, -1, token); + var commandParamsWriter = new MonoBinaryWriter(parms); + commandParamsWriter.Write(methodId); + commandParamsWriter.Write(valueTypeBuffer); + commandParamsWriter.Write(0); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdVM.InvokeMethod, parms, token); + retDebuggerCmdReader.ReadByte(); //number of objects returned. + return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, varName, false, -1, token); } public async Task CreateJArrayForProperties(SessionId sessionId, int typeId, byte[] object_buffer, JArray attributes, bool isAutoExpandable, string objectId, bool isOwn, CancellationToken token) { JArray ret = new JArray(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(typeId); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, command_params, token); - var nProperties = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); + var nProperties = retDebuggerCmdReader.ReadInt32(); for (int i = 0 ; i < nProperties; i++) { - ret_debugger_cmd_reader.ReadInt32(); //propertyId - string propertyNameStr = ret_debugger_cmd_reader.ReadString(); - var getMethodId = ret_debugger_cmd_reader.ReadInt32(); - ret_debugger_cmd_reader.ReadInt32(); //setmethod - var attrs = ret_debugger_cmd_reader.ReadInt32(); //attrs + retDebuggerCmdReader.ReadInt32(); //propertyId + string propertyNameStr = retDebuggerCmdReader.ReadString(); + 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)) continue; JObject propRet = null; @@ -1041,7 +1136,7 @@ public async Task CreateJArrayForProperties(SessionId sessionId, int typ get = new { type = "function", - objectId = $"{objectId}:method_id:{getMethodId}", + objectId = $"{objectId}:methodId:{getMethodId}", className = "Function", description = "get " + propertyNameStr + " ()", methodId = getMethodId, @@ -1059,30 +1154,30 @@ public async Task CreateJArrayForProperties(SessionId sessionId, int typ public async Task GetPointerContent(SessionId sessionId, int pointerId, CancellationToken token) { var ret = new List(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.WriteLong(pointerValues[pointerId].address); - command_params_writer.Write(pointerValues[pointerId].typeId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdPointer.GetValue, command_params, token); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.WriteLong(pointerValues[pointerId].address); + commandParamsWriter.Write(pointerValues[pointerId].typeId); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdPointer.GetValue, commandParams, token); var varName = pointerValues[pointerId].varName; if (int.TryParse(varName, out _)) varName = $"[{varName}]"; - return await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, "*" + varName, false, -1, token); + return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "*" + varName, false, -1, token); } public async Task GetPropertiesValuesOfValueType(SessionId sessionId, int valueTypeId, CancellationToken token) { JArray ret = new JArray(); var valueType = valueTypes[valueTypeId]; - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(valueType.typeId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetParents, command_params, token); - var parentsCount = ret_debugger_cmd_reader.ReadInt32(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(valueType.typeId); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetParents, commandParams, token); + var parentsCount = retDebuggerCmdReader.ReadInt32(); List typesToGetProperties = new List(); typesToGetProperties.Add(valueType.typeId); for (int i = 0 ; i < parentsCount; i++) { - typesToGetProperties.Add(ret_debugger_cmd_reader.ReadInt32()); + typesToGetProperties.Add(retDebuggerCmdReader.ReadInt32()); } for (int i = 0 ; i < typesToGetProperties.Count; i++) { @@ -1155,12 +1250,12 @@ public JObject CreateJObjectForChar(int value) return CreateJObject(description, "symbol", description, true); } - public async Task CreateJObjectForPtr(SessionId sessionId, ElementType etype, MonoBinaryReader ret_debugger_cmd_reader, string name, CancellationToken token) + public async Task CreateJObjectForPtr(SessionId sessionId, ElementType etype, MonoBinaryReader retDebuggerCmdReader, string name, CancellationToken token) { string type; string value; - long valueAddress = ret_debugger_cmd_reader.ReadLong(); - var typeId = ret_debugger_cmd_reader.ReadInt32(); + long valueAddress = retDebuggerCmdReader.ReadLong(); + var typeId = retDebuggerCmdReader.ReadInt32(); var className = ""; if (etype == ElementType.FnPtr) className = "(*())"; //to keep the old behavior @@ -1183,24 +1278,24 @@ 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 ret_debugger_cmd_reader, CancellationToken token) + public async Task CreateJObjectForString(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { - var string_id = ret_debugger_cmd_reader.ReadInt32(); + var string_id = retDebuggerCmdReader.ReadInt32(); var value = await GetStringValue(sessionId, string_id, token); return CreateJObject(value, "string", value, false); } - public async Task CreateJObjectForArray(SessionId sessionId, MonoBinaryReader ret_debugger_cmd_reader, CancellationToken token) + public async Task CreateJObjectForArray(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { - var objectId = ret_debugger_cmd_reader.ReadInt32(); + var objectId = retDebuggerCmdReader.ReadInt32(); var value = await GetClassNameFromObject(sessionId, objectId, token); var length = await GetArrayLength(sessionId, objectId, token); return CreateJObject(null, "object", $"{value.ToString()}({length})", false, value.ToString(), "dotnet:array:" + objectId, null, "array"); } - public async Task CreateJObjectForObject(SessionId sessionId, MonoBinaryReader ret_debugger_cmd_reader, int typeIdFromAttribute, CancellationToken token) + public async Task CreateJObjectForObject(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, int typeIdFromAttribute, CancellationToken token) { - var objectId = ret_debugger_cmd_reader.ReadInt32(); + var objectId = retDebuggerCmdReader.ReadInt32(); var className = ""; var type_id = await GetTypeIdFromObject(sessionId, objectId, false, token); className = await GetTypeName(sessionId, type_id[0], token); @@ -1221,22 +1316,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 ret_debugger_cmd_reader, string name, long initialPos, CancellationToken token) + public async Task CreateJObjectForValueType(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, string name, long initialPos, CancellationToken token) { JObject fieldValueType = null; - var isEnum = ret_debugger_cmd_reader.ReadByte(); - var isBoxed = ret_debugger_cmd_reader.ReadByte() == 1; - var typeId = ret_debugger_cmd_reader.ReadInt32(); + var isEnum = retDebuggerCmdReader.ReadByte(); + var isBoxed = retDebuggerCmdReader.ReadByte() == 1; + var typeId = retDebuggerCmdReader.ReadInt32(); var className = await GetTypeName(sessionId, typeId, token); var description = className; - var numFields = ret_debugger_cmd_reader.ReadInt32(); + var numFields = retDebuggerCmdReader.ReadInt32(); var fields = await GetTypeFields(sessionId, typeId, token); JArray valueTypeFields = new JArray(); if (className.IndexOf("System.Nullable<") == 0) //should we call something on debugger-agent to check??? { - ret_debugger_cmd_reader.ReadByte(); //ignoring the boolean type - var isNull = ret_debugger_cmd_reader.ReadInt32(); - var value = await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, name, false, -1, token); + retDebuggerCmdReader.ReadByte(); //ignoring the boolean type + var isNull = retDebuggerCmdReader.ReadInt32(); + var value = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, name, false, -1, token); if (isNull != 0) return value; else @@ -1244,21 +1339,21 @@ public async Task CreateJObjectForValueType(SessionId sessionId, MonoBi } for (int i = 0; i < numFields ; i++) { - fieldValueType = await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, fields.ElementAt(i).Name, true, fields.ElementAt(i).TypeId, token); + fieldValueType = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, fields.ElementAt(i).Name, true, fields.ElementAt(i).TypeId, token); valueTypeFields.Add(fieldValueType); } - long endPos = ret_debugger_cmd_reader.BaseStream.Position; + long endPos = retDebuggerCmdReader.BaseStream.Position; var valueTypeId = Interlocked.Increment(ref debugger_object_id); - ret_debugger_cmd_reader.BaseStream.Position = initialPos; + retDebuggerCmdReader.BaseStream.Position = initialPos; byte[] valueTypeBuffer = new byte[endPos - initialPos]; - ret_debugger_cmd_reader.Read(valueTypeBuffer, 0, (int)(endPos - initialPos)); - ret_debugger_cmd_reader.BaseStream.Position = endPos; + retDebuggerCmdReader.Read(valueTypeBuffer, 0, (int)(endPos - initialPos)); + retDebuggerCmdReader.BaseStream.Position = endPos; valueTypes[valueTypeId] = new ValueTypeClass(name, valueTypeBuffer, valueTypeFields, typeId, AutoExpandable(className), valueTypeId); if (AutoInvokeToString(className) || isEnum == 1) { - int method_id = await GetMethodIdByName(sessionId, typeId, "ToString", token); - var retMethod = await InvokeMethod(sessionId, valueTypeBuffer, method_id, "methodRet", token); + int methodId = await GetMethodIdByName(sessionId, typeId, "ToString", token); + var retMethod = await InvokeMethod(sessionId, valueTypeBuffer, methodId, "methodRet", token); description = retMethod["value"]?["value"].Value(); if (className.Equals("System.Guid")) description = description.ToUpper(); //to keep the old behavior @@ -1269,16 +1364,16 @@ 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 ret_debugger_cmd_reader, CancellationToken token) + public async Task CreateJObjectForNull(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { string className = ""; - ElementType variableType = (ElementType)ret_debugger_cmd_reader.ReadByte(); + ElementType variableType = (ElementType)retDebuggerCmdReader.ReadByte(); switch (variableType) { case ElementType.String: case ElementType.Class: { - var type_id = ret_debugger_cmd_reader.ReadInt32(); + var type_id = retDebuggerCmdReader.ReadInt32(); className = await GetTypeName(sessionId, type_id, token); break; @@ -1286,18 +1381,18 @@ public async Task CreateJObjectForNull(SessionId sessionId, MonoBinaryR case ElementType.SzArray: case ElementType.Array: { - ElementType byte_type = (ElementType)ret_debugger_cmd_reader.ReadByte(); - var rank = ret_debugger_cmd_reader.ReadInt32(); + ElementType byte_type = (ElementType)retDebuggerCmdReader.ReadByte(); + var rank = retDebuggerCmdReader.ReadInt32(); if (byte_type == ElementType.Class) { - var internal_type_id = ret_debugger_cmd_reader.ReadInt32(); + var internal_type_id = retDebuggerCmdReader.ReadInt32(); } - var type_id = ret_debugger_cmd_reader.ReadInt32(); + var type_id = retDebuggerCmdReader.ReadInt32(); className = await GetTypeName(sessionId, type_id, token); break; } default: { - var type_id = ret_debugger_cmd_reader.ReadInt32(); + var type_id = retDebuggerCmdReader.ReadInt32(); className = await GetTypeName(sessionId, type_id, token); break; } @@ -1305,10 +1400,10 @@ public async Task CreateJObjectForNull(SessionId sessionId, MonoBinaryR return CreateJObject(null, "object", className, false, className, null, null, "null"); } - public async Task CreateJObjectForVariableValue(SessionId sessionId, MonoBinaryReader ret_debugger_cmd_reader, string name, bool isOwn, int typeIdFromAttribute, CancellationToken token) + public async Task CreateJObjectForVariableValue(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, string name, bool isOwn, int typeIdFromAttribute, CancellationToken token) { - long initialPos = ret_debugger_cmd_reader == null ? 0 : ret_debugger_cmd_reader.BaseStream.Position; - ElementType etype = (ElementType)ret_debugger_cmd_reader.ReadByte(); + long initialPos = retDebuggerCmdReader == null ? 0 : retDebuggerCmdReader.BaseStream.Position; + ElementType etype = (ElementType)retDebuggerCmdReader.ReadByte(); JObject ret = null; switch (etype) { case ElementType.I: @@ -1317,108 +1412,114 @@ public async Task CreateJObjectForVariableValue(SessionId sessionId, Mo case (ElementType)ValueTypeId.Type: case (ElementType)ValueTypeId.VType: case (ElementType)ValueTypeId.FixedArray: - ret = new JObject{{"Type", "void"}}; + ret = JObject.FromObject(new { + value = new + { + type = "void", + value = "void", + description = "void" + }}); break; case ElementType.Boolean: { - var value = ret_debugger_cmd_reader.ReadInt32(); + var value = retDebuggerCmdReader.ReadInt32(); ret = CreateJObjectForBoolean(value); break; } case ElementType.I1: { - var value = ret_debugger_cmd_reader.ReadSByte(); + var value = retDebuggerCmdReader.ReadSByte(); ret = CreateJObjectForNumber(value); break; } case ElementType.I2: case ElementType.I4: { - var value = ret_debugger_cmd_reader.ReadInt32(); + var value = retDebuggerCmdReader.ReadInt32(); ret = CreateJObjectForNumber(value); break; } case ElementType.U1: { - var value = ret_debugger_cmd_reader.ReadUByte(); + var value = retDebuggerCmdReader.ReadUByte(); ret = CreateJObjectForNumber(value); break; } case ElementType.U2: { - var value = ret_debugger_cmd_reader.ReadUShort(); + var value = retDebuggerCmdReader.ReadUShort(); ret = CreateJObjectForNumber(value); break; } case ElementType.U4: { - var value = ret_debugger_cmd_reader.ReadUInt32(); + var value = retDebuggerCmdReader.ReadUInt32(); ret = CreateJObjectForNumber(value); break; } case ElementType.R4: { - float value = BitConverter.Int32BitsToSingle(ret_debugger_cmd_reader.ReadInt32()); + float value = BitConverter.Int32BitsToSingle(retDebuggerCmdReader.ReadInt32()); ret = CreateJObjectForNumber(value); break; } case ElementType.Char: { - var value = ret_debugger_cmd_reader.ReadInt32(); + var value = retDebuggerCmdReader.ReadInt32(); ret = CreateJObjectForChar(value); break; } case ElementType.I8: { - long value = ret_debugger_cmd_reader.ReadLong(); + long value = retDebuggerCmdReader.ReadLong(); ret = CreateJObjectForNumber(value); break; } case ElementType.U8: { - ulong high = (ulong) ret_debugger_cmd_reader.ReadInt32(); - ulong low = (ulong) ret_debugger_cmd_reader.ReadInt32(); + ulong high = (ulong) retDebuggerCmdReader.ReadInt32(); + ulong low = (ulong) retDebuggerCmdReader.ReadInt32(); var value = ((high << 32) | low); ret = CreateJObjectForNumber(value); break; } case ElementType.R8: { - double value = ret_debugger_cmd_reader.ReadDouble(); + double value = retDebuggerCmdReader.ReadDouble(); ret = CreateJObjectForNumber(value); break; } case ElementType.FnPtr: case ElementType.Ptr: { - ret = await CreateJObjectForPtr(sessionId, etype, ret_debugger_cmd_reader, name, token); + ret = await CreateJObjectForPtr(sessionId, etype, retDebuggerCmdReader, name, token); break; } case ElementType.String: { - ret = await CreateJObjectForString(sessionId, ret_debugger_cmd_reader, token); + ret = await CreateJObjectForString(sessionId, retDebuggerCmdReader, token); break; } case ElementType.SzArray: case ElementType.Array: { - ret = await CreateJObjectForArray(sessionId, ret_debugger_cmd_reader, token); + ret = await CreateJObjectForArray(sessionId, retDebuggerCmdReader, token); break; } case ElementType.Class: case ElementType.Object: { - ret = await CreateJObjectForObject(sessionId, ret_debugger_cmd_reader, typeIdFromAttribute, token); + ret = await CreateJObjectForObject(sessionId, retDebuggerCmdReader, typeIdFromAttribute, token); break; } case ElementType.ValueType: { - ret = await CreateJObjectForValueType(sessionId, ret_debugger_cmd_reader, name, initialPos, token); + ret = await CreateJObjectForValueType(sessionId, retDebuggerCmdReader, name, initialPos, token); break; } case (ElementType)ValueTypeId.Null: { - ret = await CreateJObjectForNull(sessionId, ret_debugger_cmd_reader, token); + ret = await CreateJObjectForNull(sessionId, retDebuggerCmdReader, token); break; } } @@ -1430,32 +1531,32 @@ public async Task CreateJObjectForVariableValue(SessionId sessionId, Mo public async Task IsAsyncMethod(SessionId sessionId, int methodId, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(methodId); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(methodId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdMethod.AsyncDebugInfo, command_params, token); - return ret_debugger_cmd_reader.ReadByte() == 1 ; //token + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdMethod.AsyncDebugInfo, commandParams, token); + return retDebuggerCmdReader.ReadByte() == 1 ; //token } - public async Task StackFrameGetValues(SessionId sessionId, MethodInfo method, int thread_id, int frame_id, VarInfo[] var_ids, CancellationToken token) + public async Task StackFrameGetValues(SessionId sessionId, MethodInfo method, int thread_id, int frame_id, VarInfo[] varIds, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - MonoBinaryReader ret_debugger_cmd_reader = null; - command_params_writer.Write(thread_id); - command_params_writer.Write(frame_id); - command_params_writer.Write(var_ids.Length); - foreach (var var in var_ids) + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + MonoBinaryReader retDebuggerCmdReader = null; + commandParamsWriter.Write(thread_id); + commandParamsWriter.Write(frame_id); + commandParamsWriter.Write(varIds.Length); + foreach (var var in varIds) { - command_params_writer.Write(var.Index); + commandParamsWriter.Write(var.Index); } if (await IsAsyncMethod(sessionId, method.DebuggerId, token)) { - ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetThis, command_params, token); - ret_debugger_cmd_reader.ReadByte(); //ignore type - var objectId = ret_debugger_cmd_reader.ReadInt32(); + retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetThis, commandParams, token); + retDebuggerCmdReader.ReadByte(); //ignore type + var objectId = retDebuggerCmdReader.ReadInt32(); var asyncLocals = await GetObjectValues(sessionId, objectId, true, false, false, false, token); asyncLocals = new JArray(asyncLocals.Where( asyncLocal => !asyncLocal["name"].Value().Contains("<>") || asyncLocal["name"].Value().EndsWith("__this"))); foreach (var asyncLocal in asyncLocals) @@ -1469,16 +1570,16 @@ public async Task StackFrameGetValues(SessionId sessionId, MethodInfo me } JArray locals = new JArray(); - ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetValues, command_params, token); - foreach (var var in var_ids) + retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetValues, commandParams, token); + foreach (var var in varIds) { - var var_json = await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, var.Name, false, -1, token); + var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, var.Name, false, -1, token); locals.Add(var_json); } if (!method.IsStatic()) { - ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetThis, command_params, token); - var var_json = await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, "this", false, -1, token); + retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetThis, commandParams, token); + var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "this", false, -1, token); var_json.Add("fieldOffset", -1); locals.Add(var_json); } @@ -1504,21 +1605,21 @@ public async Task GetValueTypeProxy(SessionId sessionId, int valueTypeId return valueTypes[valueTypeId].valueTypeProxy; valueTypes[valueTypeId].valueTypeProxy = new JArray(valueTypes[valueTypeId].valueTypeJson); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(valueTypes[valueTypeId].typeId); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(valueTypes[valueTypeId].typeId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, command_params, token); - var nProperties = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); + var nProperties = retDebuggerCmdReader.ReadInt32(); for (int i = 0 ; i < nProperties; i++) { - ret_debugger_cmd_reader.ReadInt32(); //propertyId - string propertyNameStr = ret_debugger_cmd_reader.ReadString(); + retDebuggerCmdReader.ReadInt32(); //propertyId + string propertyNameStr = retDebuggerCmdReader.ReadString(); - var getMethodId = ret_debugger_cmd_reader.ReadInt32(); - ret_debugger_cmd_reader.ReadInt32(); //setmethod - ret_debugger_cmd_reader.ReadInt32(); //attrs + var getMethodId = retDebuggerCmdReader.ReadInt32(); + retDebuggerCmdReader.ReadInt32(); //setmethod + retDebuggerCmdReader.ReadInt32(); //attrs if (await MethodIsStatic(sessionId, getMethodId, token)) continue; var command_params_to_proxy = new MemoryStream(); @@ -1542,16 +1643,16 @@ public async Task GetValueTypeProxy(SessionId sessionId, int valueTypeId public async Task GetArrayValues(SessionId sessionId, int arrayId, CancellationToken token) { var length = await GetArrayLength(sessionId, arrayId, token); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(arrayId); - command_params_writer.Write(0); - command_params_writer.Write(length); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetValues, command_params, token); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(arrayId); + commandParamsWriter.Write(0); + commandParamsWriter.Write(length); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetValues, commandParams, token); JArray array = new JArray(); for (int i = 0 ; i < length ; i++) { - var var_json = await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, i.ToString(), false, -1, token); + var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, i.ToString(), false, -1, token); array.Add(var_json); } return array; @@ -1559,25 +1660,25 @@ public async Task GetArrayValues(SessionId sessionId, int arrayId, Cance public async Task EnableExceptions(SessionId sessionId, string state, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write((byte)EventKind.Exception); - command_params_writer.Write((byte)SuspendPolicy.None); - command_params_writer.Write((byte)1); - command_params_writer.Write((byte)ModifierKind.ExceptionOnly); - command_params_writer.Write(0); //exc_class + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((byte)EventKind.Exception); + commandParamsWriter.Write((byte)SuspendPolicy.None); + commandParamsWriter.Write((byte)1); + commandParamsWriter.Write((byte)ModifierKind.ExceptionOnly); + commandParamsWriter.Write(0); //exc_class if (state == "all") - command_params_writer.Write((byte)1); //caught + commandParamsWriter.Write((byte)1); //caught else - command_params_writer.Write((byte)0); //caught + commandParamsWriter.Write((byte)0); //caught if (state == "uncaught" || state == "all") - command_params_writer.Write((byte)1); //uncaught + commandParamsWriter.Write((byte)1); //uncaught else - command_params_writer.Write((byte)0); //uncaught - command_params_writer.Write((byte)1);//subclasses - command_params_writer.Write((byte)0);//not_filtered_feature - command_params_writer.Write((byte)0);//everything_else - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdEventRequest.Set, command_params, token); + commandParamsWriter.Write((byte)0); //uncaught + 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); return true; } public async Task GetObjectValues(SessionId sessionId, int objectId, bool withProperties, bool withSetter, bool accessorPropertiesOnly, bool ownProperties, CancellationToken token) @@ -1608,23 +1709,23 @@ public async Task GetObjectValues(SessionId sessionId, int objectId, boo var fields = await GetTypeFields(sessionId, typeId[i], token); JArray objectFields = new JArray(); - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(objectId); - command_params_writer.Write(fields.Count); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(objectId); + commandParamsWriter.Write(fields.Count); foreach (var field in fields) { - command_params_writer.Write(field.Id); + commandParamsWriter.Write(field.Id); } - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefGetValues, command_params, token); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdObject.RefGetValues, commandParams, token); foreach (var field in fields) { - long initialPos = ret_debugger_cmd_reader.BaseStream.Position; - int valtype = ret_debugger_cmd_reader.ReadByte(); - ret_debugger_cmd_reader.BaseStream.Position = initialPos; - var fieldValue = await CreateJObjectForVariableValue(sessionId, ret_debugger_cmd_reader, field.Name, i == 0, field.TypeId, token); + 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, token); if (ret.Where(attribute => attribute["name"].Value().Equals(fieldValue["name"].Value())).Any()) { continue; @@ -1652,8 +1753,8 @@ public async Task GetObjectValues(SessionId sessionId, int objectId, boo if (!withProperties) return ret; var command_params_obj = new MemoryStream(); - var command_params_obj_writer = new MonoBinaryWriter(command_params_obj); - command_params_obj_writer.WriteObj(new DotnetObjectId("object", $"{objectId}"), this); + var commandParamsObjWriter = new MonoBinaryWriter(command_params_obj); + commandParamsObjWriter.WriteObj(new DotnetObjectId("object", $"{objectId}"), this); var props = await CreateJArrayForProperties(sessionId, typeId[i], command_params_obj.ToArray(), ret, false, $"dotnet:object:{objectId}", i == 0, token); ret = new JArray(ret.Union(props)); @@ -1706,19 +1807,19 @@ public async Task GetObjectProxy(SessionId sessionId, int objectId, Canc var typeIds = await GetTypeIdFromObject(sessionId, objectId, true, token); foreach (var typeId in typeIds) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - command_params_writer.Write(typeId); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); - var ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, command_params, token); - var nProperties = ret_debugger_cmd_reader.ReadInt32(); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); + var nProperties = retDebuggerCmdReader.ReadInt32(); for (int i = 0 ; i < nProperties; i++) { - ret_debugger_cmd_reader.ReadInt32(); //propertyId - string propertyNameStr = ret_debugger_cmd_reader.ReadString(); - var getMethodId = ret_debugger_cmd_reader.ReadInt32(); - var setMethodId = ret_debugger_cmd_reader.ReadInt32(); //setmethod - var attrValue = ret_debugger_cmd_reader.ReadInt32(); //attrs + retDebuggerCmdReader.ReadInt32(); //propertyId + string propertyNameStr = retDebuggerCmdReader.ReadString(); + var getMethodId = retDebuggerCmdReader.ReadInt32(); + var setMethodId = retDebuggerCmdReader.ReadInt32(); //setmethod + var attrValue = retDebuggerCmdReader.ReadInt32(); //attrs //Console.WriteLine($"{propertyNameStr} - {attrValue}"); if (ret.Where(attribute => attribute["name"].Value().Equals(propertyNameStr)).Any()) { @@ -1770,19 +1871,19 @@ public async Task GetObjectProxy(SessionId sessionId, int objectId, Canc public async Task SetVariableValue(SessionId sessionId, int thread_id, int frame_id, int varId, string newValue, CancellationToken token) { - var command_params = new MemoryStream(); - var command_params_writer = new MonoBinaryWriter(command_params); - MonoBinaryReader ret_debugger_cmd_reader = null; - command_params_writer.Write(thread_id); - command_params_writer.Write(frame_id); - command_params_writer.Write(1); - command_params_writer.Write(varId); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + MonoBinaryReader retDebuggerCmdReader = null; + commandParamsWriter.Write(thread_id); + commandParamsWriter.Write(frame_id); + commandParamsWriter.Write(1); + commandParamsWriter.Write(varId); JArray locals = new JArray(); - ret_debugger_cmd_reader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetValues, command_params, token); - int etype = ret_debugger_cmd_reader.ReadByte(); + retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetValues, commandParams, token); + int etype = retDebuggerCmdReader.ReadByte(); try { - ret_debugger_cmd_reader = await SendDebuggerAgentCommandWithParms(sessionId, CmdFrame.SetValues, command_params, etype, newValue, token); + retDebuggerCmdReader = await SendDebuggerAgentCommandWithParms(sessionId, CmdFrame.SetValues, commandParams, etype, newValue, token); } catch (Exception) { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index 993e6165cc0ab..d6803ee8670fd 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -502,6 +502,105 @@ async Task EvaluateOnCallFrameFail(string call_frame_id, params (string expressi AssertEqual(arg.class_name, res.Error["result"]?["className"]?.Value(), $"Error className did not match for expression '{arg.expression}'"); } } + + + [Fact] + public async Task EvaluateSimpleMethodCallsError() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + var (_, res) = await EvaluateOnCallFrame(id, "this.objToTest.MyMethodWrong()", expect_ok: false ); + AssertEqual("Method 'MyMethodWrong' not found in type 'DebuggerTests.EvaluateMethodTestsClass.ParmToTest'", res.Error["message"]?.Value(), "wrong error message"); + + (_, res) = await EvaluateOnCallFrame(id, "this.objToTest.MyMethod(1)", expect_ok: false ); + AssertEqual("Unable to evaluate method 'MyMethod'", res.Error["message"]?.Value(), "wrong error message"); + + (_, res) = await EvaluateOnCallFrame(id, "this.CallMethodWithParm(\"1\")", expect_ok: false ); + AssertEqual("Unable to evaluate method 'CallMethodWithParm'", res.Error["message"]?.Value(), "wrong error message"); + + (_, res) = await EvaluateOnCallFrame(id, "this.ParmToTestObjNull.MyMethod()", expect_ok: false ); + AssertEqual("Object reference not set to an instance of an object.", res.Error["message"]?.Value(), "wrong error message"); + + (_, res) = await EvaluateOnCallFrame(id, "this.ParmToTestObjException.MyMethod()", expect_ok: false ); + AssertEqual("Object reference not set to an instance of an object.", res.Error["message"]?.Value(), "wrong error message"); + }); + + [Fact] + public async Task EvaluateSimpleMethodCallsWithoutParms() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + await EvaluateOnCallFrameAndCheck(id, + ("this.CallMethod()", TNumber(1)), + ("this.CallMethod()", TNumber(1)), + ("this.ParmToTestObj.MyMethod()", TString("methodOK")), + ("this.objToTest.MyMethod()", TString("methodOK"))); + }); + + + [Fact] + public async Task EvaluateSimpleMethodCallsWithConstParms() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + await EvaluateOnCallFrameAndCheck(id, + ("this.CallMethodWithParm(10)", TNumber(11)), + ("this.CallMethodWithMultipleParms(10, 10)", TNumber(21)), + ("this.CallMethodWithParmBool(true)", TString("TRUE")), + ("this.CallMethodWithParmBool(false)", TString("FALSE")), + ("this.CallMethodWithParmString(\"concat\")", TString("str_const_concat")), + ("this.CallMethodWithParm(10) + this.a", TNumber(12)), + ("this.CallMethodWithObj(null)", TNumber(-1)), + ("this.CallMethodWithChar('a')", TString("str_const_a"))); + }); + + [Fact] + public async Task EvaluateSimpleMethodCallsWithVariableParms() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + await EvaluateOnCallFrameAndCheck(id, + ("this.CallMethodWithParm(this.a)", TNumber(2)), + ("this.CallMethodWithMultipleParms(this.a, 10)", TNumber(12)), + ("this.CallMethodWithParmString(this.str)", TString("str_const_str_const_")), + ("this.CallMethodWithParmBool(this.t)", TString("TRUE")), + ("this.CallMethodWithParmBool(this.f)", TString("FALSE")), + ("this.CallMethodWithParm(this.a) + this.a", TNumber(3)), + ("this.CallMethodWithObj(this.objToTest)", TNumber(10))); + }); + + + [Fact] + public async Task EvaluateSimpleMethodCallsCheckChangedValue() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + var frame = pause_location["callFrames"][0]; + var props = await GetObjectOnFrame(frame, "this"); + CheckNumber(props, "a", 1); + + await EvaluateOnCallFrameAndCheck(id, + ("this.CallMethodChangeValue()", TObject("object", is_null : true))); + + frame = pause_location["callFrames"][0]; + props = await GetObjectOnFrame(frame, "this"); + CheckNumber(props, "a", 11); + }); } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs index 4054c6a2cea11..b45825acfcbd8 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs @@ -21,18 +21,18 @@ await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method('[debugger-test] Math:IntAdd', 1, 2); })", null, -1, -1, "IntAdd"); - var var_ids = new[] + var varIds = new[] { new { index = 0, name = "one" }, }; - var scope_id = "-12"; - var expression = $"MONO.mono_wasm_get_variables({scope_id}, {JsonConvert.SerializeObject(var_ids)})"; + var scopeId = "-12"; + var expression = $"MONO.mono_wasm_get_variables({scopeId}, {JsonConvert.SerializeObject(varIds)})"; var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), token); Assert.False(res.IsOk); - scope_id = "30000"; - expression = $"MONO.mono_wasm_get_variables({scope_id}, {JsonConvert.SerializeObject(var_ids)})"; + scopeId = "30000"; + expression = $"MONO.mono_wasm_get_variables({scopeId}, {JsonConvert.SerializeObject(varIds)})"; res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), token); Assert.False(res.IsOk); } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs index a5fbd57a300f5..1583ce1fd6f86 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs @@ -309,4 +309,101 @@ public async Task GenericInstanceMethodAsync(int g, int h, string valStrin return await Task.FromResult(default(T)); } } + public class EvaluateMethodTestsClass + { + public class ParmToTest + { + public int a; + public int b; + public ParmToTest() + { + a = 10; + b = 10; + } + public string MyMethod() + { + return "methodOK"; + } + } + public class TestEvaluate + { + public int a; + public int b; + public int c; + public string str = "str_const_"; + public bool t = true; + public bool f = false; + public ParmToTest objToTest; + public ParmToTest ParmToTestObj => objToTest; + public ParmToTest ParmToTestObjNull => null; + public ParmToTest ParmToTestObjException => throw new Exception("error2"); + public void run(int g, int h, string a, string valString, int this_a) + { + objToTest = new ParmToTest(); + int d = g + 1; + int e = g + 2; + int f = g + 3; + int i = d + e + f; + this.a = 1; + b = 2; + c = 3; + this.a = this.a + 1; + b = b + 1; + c = c + 1; + } + + public int CallMethod() + { + return a; + } + + public int CallMethodWithParm(int parm) + { + return a + parm; + } + + public void CallMethodChangeValue() + { + a = a + 10; + } + + public int CallMethodWithMultipleParms(int parm, int parm2) + { + return a + parm + parm2; + } + + public string CallMethodWithParmString(string parm) + { + return str + parm; + } + + public string CallMethodWithParmBool(bool parm) + { + if (parm) + return "TRUE"; + return "FALSE"; + } + + public int CallMethodWithObj(ParmToTest parm) + { + if (parm == null) + return -1; + return parm.a; + } + + + public string CallMethodWithChar(char parm) + { + return str + parm; + } + } + + public static void EvaluateMethods() + { + TestEvaluate f = new TestEvaluate(); + f.run(100, 200, "9000", "test", 45); + } + + } + }