protected override async Task <bool> SendCallStack(SessionId sessionId, ExecutionContext context, string reason, int thread_id, Breakpoint bp, JObject data, JObject args, EventKind event_kind, CancellationToken token) { Frame frame = null; var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(thread_id); commandParamsWriter.Write(0); commandParamsWriter.Write(1); var retDebuggerCmdReader = await context.SdbAgent.SendDebuggerAgentCommand(CmdThread.GetFrameInfo, commandParamsWriter, token); var frame_count = retDebuggerCmdReader.ReadInt32(); if (frame_count > 0) { var frame_id = retDebuggerCmdReader.ReadInt32(); var methodId = retDebuggerCmdReader.ReadInt32(); var il_pos = retDebuggerCmdReader.ReadInt32(); retDebuggerCmdReader.ReadByte(); var method = await context.SdbAgent.GetMethodInfo(methodId, token); if (method is null) { return(false); } if (await ShouldSkipMethod(sessionId, context, event_kind, 0, method, token)) { await SendResume(sessionId, token); return(true); } SourceLocation location = method?.Info.GetLocationByIl(il_pos); if (location == null) { return(false); } Log("debug", $"frame il offset: {il_pos} method token: {method.Info.Token} assembly name: {method.Info.Assembly.Name}"); Log("debug", $"\tmethod {method.Name} location: {location}"); frame = new Frame(method, location, frame_id); context.CallStack = new List <Frame>(); context.CallStack.Add(frame); } if (!await EvaluateCondition(sessionId, context, frame, bp, token)) { context.ClearState(); await SendResume(sessionId, token); return(true); } args["why"]["type"] = context.PauseKind; await SendEvent(sessionId, "", args, token); return(true); }
public async Task <JObject> TryToRunOnLoadedClasses(string varName, CancellationToken token) { string classNameToFind = ""; string[] parts = varName.Split("."); var typeId = -1; foreach (string part in parts) { if (classNameToFind.Length > 0) { classNameToFind += "."; } classNameToFind += part.Trim(); if (typeId != -1) { var fields = await proxy.SdbHelper.GetTypeFields(sessionId, typeId, token); foreach (var field in fields) { if (field.Name == part.Trim()) { var isInitialized = await proxy.SdbHelper.TypeIsInitialized(sessionId, typeId, token); if (isInitialized == 0) { isInitialized = await proxy.SdbHelper.TypeInitialize(sessionId, typeId, token); } var valueRet = await proxy.SdbHelper.GetFieldValue(sessionId, typeId, field.Id, token); return(await GetValueFromObject(valueRet, token)); } } var methodId = await proxy.SdbHelper.GetPropertyMethodIdByName(sessionId, typeId, part.Trim(), token); if (methodId != -1) { var commandParamsObj = new MemoryStream(); var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); commandParamsObjWriter.Write(0); //param count var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); return(await GetValueFromObject(retMethod, token)); } } var store = await proxy.LoadStore(sessionId, token); foreach (var asm in store.assemblies) { var type = asm.GetTypeByName(classNameToFind); if (type != null) { var assemblyId = await proxy.SdbHelper.GetAssemblyId(sessionId, type.assembly.Name, token); typeId = await proxy.SdbHelper.GetTypeIdFromToken(sessionId, assemblyId, type.Token, token); } } } return(null); }
public async Task <JObject> Resolve(InvocationExpressionSyntax method, Dictionary <string, JObject> 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(); } else if (expr is IdentifierNameSyntax) { if (scopeCache.ObjectFields.TryGetValue("this", out JObject valueRet)) { rootObject = await GetValueFromObject(valueRet, token); methodName = expr.ToString(); } } if (rootObject != null) { DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), 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}'"); } }
private async Task <bool> GetFrames(SessionId sessionId, ExecutionContext context, JObject args, CancellationToken token) { var ctx = context as FirefoxExecutionContext; var orig_callframes = await SendCommand(sessionId, "frames", args, token); var callFrames = new List <object>(); var frames = new List <Frame>(); var commandParamsWriter = new MonoBinaryWriter(); commandParamsWriter.Write(context.ThreadId); commandParamsWriter.Write(0); commandParamsWriter.Write(-1); var retDebuggerCmdReader = await context.SdbAgent.SendDebuggerAgentCommand(CmdThread.GetFrameInfo, commandParamsWriter, token); var frame_count = retDebuggerCmdReader.ReadInt32(); for (int j = 0; j < frame_count; j++) { var frame_id = retDebuggerCmdReader.ReadInt32(); var methodId = retDebuggerCmdReader.ReadInt32(); var il_pos = retDebuggerCmdReader.ReadInt32(); retDebuggerCmdReader.ReadByte(); MethodInfoWithDebugInformation method = await context.SdbAgent.GetMethodInfo(methodId, token); if (method is null) { continue; } SourceLocation location = method.Info?.GetLocationByIl(il_pos); if (location == null) { continue; } Log("debug", $"frame il offset: {il_pos} method token: {method.Info.Token} assembly name: {method.Info.Assembly.Name}"); Log("debug", $"\tmethod {method.Name} location: {location}"); frames.Add(new Frame(method, location, frame_id)); var frameItem = JObject.FromObject(new { actor = $"dotnet:scope:{frame_id}", displayName = method.Name, type = "call", state = "on-stack", asyncCause = (string)null, where = new { actor = location.Id.ToString(), line = location.Line + 1, column = location.Column } }); if (j > 0) { frameItem.Add("depth", j); } callFrames.Add(frameItem); context.CallStack = frames; } foreach (JObject frame in orig_callframes.Value["result"]?["value"]?["frames"]) { string function_name = frame["displayName"]?.Value <string>(); if (function_name != null && !(function_name.StartsWith("Module._mono_wasm", StringComparison.Ordinal) || function_name.StartsWith("Module.mono_wasm", StringComparison.Ordinal) || function_name == "mono_wasm_fire_debugger_agent_message" || function_name == "_mono_wasm_fire_debugger_agent_message" || function_name == "(wasmcall)")) { callFrames.Add(frame); } } var o = JObject.FromObject(new { frames = callFrames, from = ctx.ThreadName }); await SendEvent(sessionId, "", o, token); return(false); }
public async Task <JObject> Resolve(InvocationExpressionSyntax method, Dictionary <string, JObject> memberAccessValues, CancellationToken token) { var methodName = ""; int isTryingLinq = 0; 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(); } else if (expr is IdentifierNameSyntax) { if (scopeCache.ObjectFields.TryGetValue("this", out JObject valueRet)) { rootObject = await GetValueFromObject(valueRet, token); methodName = expr.ToString(); } } if (rootObject != null) { DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId objectId); var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], methodName, token); var className = await sdbHelper.GetTypeNameOriginal(sessionId, typeIds[0], token); if (methodId == 0) //try to search on System.Linq.Enumerable { if (linqTypeId == -1) { linqTypeId = await sdbHelper.GetTypeByName(sessionId, "System.Linq.Enumerable", token); } methodId = await sdbHelper.GetMethodIdByName(sessionId, linqTypeId, methodName, token); if (methodId != 0) { foreach (var typeId in typeIds) { var genericTypeArgs = await sdbHelper.GetTypeParamsOrArgsForGenericType(sessionId, typeId, token); if (genericTypeArgs.Count > 0) { isTryingLinq = 1; methodId = await sdbHelper.MakeGenericMethod(sessionId, methodId, genericTypeArgs, token); break; } } } } if (methodId == 0) { var typeName = await sdbHelper.GetTypeName(sessionId, typeIds[0], token); throw new Exception($"Method '{methodName}' not found in type '{typeName}'"); } var commandParamsObj = new MemoryStream(); var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); if (isTryingLinq == 0) { commandParamsObjWriter.WriteObj(objectId, sdbHelper); } if (method.ArgumentList != null) { commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count + isTryingLinq); if (isTryingLinq == 1) { commandParamsObjWriter.WriteObj(objectId, sdbHelper); } foreach (var arg in method.ArgumentList.Arguments) { if (arg.Expression is LiteralExpressionSyntax) { if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, sdbHelper, token)) { return(null); } } if (arg.Expression is IdentifierNameSyntax) { var argParm = arg.Expression as IdentifierNameSyntax; if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], sdbHelper, token)) { return(null); } } } var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); return(await GetValueFromObject(retMethod, token)); } } return(null); } catch (Exception) { throw new Exception($"Unable to evaluate method '{methodName}'"); } }
public async Task <JObject> TryToRunOnLoadedClasses(string varName, CancellationToken token) { string classNameToFind = ""; string[] parts = varName.Split("."); var typeId = -1; foreach (string part in parts) { if (classNameToFind.Length > 0) { classNameToFind += "."; } classNameToFind += part.Trim(); if (typeId != -1) { var fields = await context.SdbAgent.GetTypeFields(typeId, token); foreach (var field in fields) { if (field.Name == part.Trim()) { var isInitialized = await context.SdbAgent.TypeIsInitialized(typeId, token); if (isInitialized == 0) { isInitialized = await context.SdbAgent.TypeInitialize(typeId, token); } var valueRet = await context.SdbAgent.GetFieldValue(typeId, field.Id, token); return(await GetValueFromObject(valueRet, token)); } } var methodId = await context.SdbAgent.GetPropertyMethodIdByName(typeId, part.Trim(), token); if (methodId != -1) { using var commandParamsObjWriter = new MonoBinaryWriter(); commandParamsObjWriter.Write(0); //param count var retMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, "methodRet", token); return(await GetValueFromObject(retMethod, token)); } } var store = await proxy.LoadStore(sessionId, token); var methodInfo = context.CallStack.FirstOrDefault(s => s.Id == scopeId)?.Method?.Info; var classNameToFindWithNamespace = string.IsNullOrEmpty(methodInfo?.TypeInfo?.Namespace) ? classNameToFind : methodInfo.TypeInfo.Namespace + "." + classNameToFind; var searchResult = await TryFindNameInAssembly(store.assemblies, classNameToFindWithNamespace); if (searchResult == null) { searchResult = await TryFindNameInAssembly(store.assemblies, classNameToFind); } if (searchResult != null) { typeId = (int)searchResult; } async Task <int?> TryGetTypeIdFromName(string typeName, AssemblyInfo assembly) { var type = assembly.GetTypeByName(typeName); if (type == null) { return(null); } return(await context.SdbAgent.GetTypeIdFromToken(assembly.DebugId, type.Token, token)); } async Task <int?> TryFindNameInAssembly(List <AssemblyInfo> assemblies, string name) { foreach (var asm in assemblies) { var typeId = await TryGetTypeIdFromName(name, asm); if (typeId != null) { return(typeId); } } return(null); } } return(null); }