예제 #1
0
        public async Task <JObject> GetValueFromObject(JToken objRet, CancellationToken token)
        {
            if (objRet["value"]?["className"]?.Value <string>() == "System.Exception")
            {
                if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    var exceptionObject = await proxy.SdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), true, false, false, true, token);

                    var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value <string>().Equals("_message"));
                    exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value <string>() + ": " + exceptionObjectMessage["value"]?["value"]?.Value <string>();
                    return(exceptionObjectMessage["value"]?.Value <JObject>());
                }
                return(objRet["value"]?.Value <JObject>());
            }

            if (objRet["value"]?.Value <JObject>() != null)
            {
                return(objRet["value"]?.Value <JObject>());
            }
            if (objRet["get"]?.Value <JObject>() != null)
            {
                if (DotnetObjectId.TryParse(objRet?["get"]?["objectIdValue"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    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 <int>(), objRet["name"].Value <string>(), token);

                    return(await GetValueFromObject(ret, token));
                }
            }
            return(null);
        }
예제 #2
0
        public async Task <JObject> GetValueFromObject(JToken objRet, CancellationToken token)
        {
            if (objRet["value"]?["className"]?.Value <string>() == "System.Exception")
            {
                if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    var exceptionObject = await context.SdbAgent.GetObjectValues(objectId.Value, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token);

                    var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value <string>().Equals("_message"));
                    exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value <string>() + ": " + exceptionObjectMessage["value"]?["value"]?.Value <string>();
                    return(exceptionObjectMessage["value"]?.Value <JObject>());
                }
                return(objRet["value"]?.Value <JObject>());
            }

            if (objRet["value"]?.Value <JObject>() != null)
            {
                return(objRet["value"]?.Value <JObject>());
            }
            if (objRet["get"]?.Value <JObject>() != null)
            {
                if (DotnetObjectId.TryParse(objRet?["get"]?["objectIdValue"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    using var commandParamsWriter = new MonoBinaryWriter();
                    commandParamsWriter.WriteObj(objectId, context.SdbAgent);
                    var ret = await context.SdbAgent.InvokeMethod(commandParamsWriter.GetParameterBuffer(), objRet["get"]["methodId"].Value <int>(), objRet["name"].Value <string>(), token);

                    return(await GetValueFromObject(ret, token));
                }
            }
            return(null);
        }
예제 #3
0
        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);
        }
예제 #4
0
    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);
    }
예제 #5
0
        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}'");
            }
        }
예제 #6
0
    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);
    }
예제 #7
0
        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}'");
            }
        }
예제 #8
0
        public async Task <JObject> Resolve(ElementAccessExpressionSyntax elementAccess, Dictionary <string, JObject> memberAccessValues, JObject indexObject, CancellationToken token)
        {
            try
            {
                JObject rootObject = null;
                string  elementAccessStrExpression = elementAccess.Expression.ToString();
                rootObject = await Resolve(elementAccessStrExpression, token);

                if (rootObject == null)
                {
                    rootObject  = indexObject;
                    indexObject = null;
                }
                if (rootObject != null)
                {
                    string elementIdxStr;
                    int    elementIdx = 0;
                    // x[1] or x[a] or x[a.b]
                    if (indexObject == null)
                    {
                        if (elementAccess.ArgumentList != null)
                        {
                            var commandParamsObj       = new MemoryStream();
                            var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
                            foreach (var arg in elementAccess.ArgumentList.Arguments)
                            {
                                // e.g. x[1]
                                if (arg.Expression is LiteralExpressionSyntax)
                                {
                                    var argParm = arg.Expression as LiteralExpressionSyntax;
                                    elementIdxStr = argParm.ToString();
                                    int.TryParse(elementIdxStr, out elementIdx);
                                }

                                // e.g. x[a] or x[a.b]
                                if (arg.Expression is IdentifierNameSyntax)
                                {
                                    var argParm = arg.Expression as IdentifierNameSyntax;

                                    // x[a.b]
                                    memberAccessValues.TryGetValue(argParm.Identifier.Text, out indexObject);

                                    // x[a]
                                    if (indexObject == null)
                                    {
                                        indexObject = await Resolve(argParm.Identifier.Text, token);
                                    }
                                    elementIdxStr = indexObject["value"].ToString();
                                    int.TryParse(elementIdxStr, out elementIdx);
                                }
                            }
                        }
                    }
                    // e.g. x[a[0]], x[a[b[1]]] etc.
                    else
                    {
                        elementIdxStr = indexObject["value"].ToString();
                        int.TryParse(elementIdxStr, out elementIdx);
                    }
                    if (elementIdx >= 0)
                    {
                        DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId objectId);
                        switch (objectId.Scheme)
                        {
                        case "array":
                            rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(objectId.Value), token);

                            return((JObject)rootObject["value"][elementIdx]["value"]);

                        case "object":
                            var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token);

                            int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], "ToArray", token);

                            var commandParamsObj       = new MemoryStream();
                            var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
                            commandParamsObjWriter.WriteObj(objectId, sdbHelper);
                            var toArrayRetMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, elementAccess.Expression.ToString(), token);

                            rootObject = await GetValueFromObject(toArrayRetMethod, token);

                            DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId arrayObjectId);
                            rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(arrayObjectId.Value), token);

                            return((JObject)rootObject["value"][elementIdx]["value"]);

                        default:
                            throw new InvalidOperationException($"Cannot apply indexing with [] to an expression of type '{objectId.Scheme}'");
                        }
                    }
                }
                return(null);
            }
            catch (Exception ex)
            {
                var e = ex;
                throw new Exception($"Unable to evaluate method '{elementAccess}'");
            }
        }
예제 #9
0
        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);
        }