Example #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 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);
        }
        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 context.SdbAgent.GetTypeIdFromObject(int.Parse(objectId.Value), true, token);

                    int methodId = await context.SdbAgent.GetMethodIdByName(typeIds[0], methodName, token);

                    var className = await context.SdbAgent.GetTypeNameOriginal(typeIds[0], token);

                    if (methodId == 0) //try to search on System.Linq.Enumerable
                    {
                        if (linqTypeId == -1)
                        {
                            linqTypeId = await context.SdbAgent.GetTypeByName("System.Linq.Enumerable", token);
                        }
                        methodId = await context.SdbAgent.GetMethodIdByName(linqTypeId, methodName, token);

                        if (methodId != 0)
                        {
                            foreach (var typeId in typeIds)
                            {
                                var genericTypeArgs = await context.SdbAgent.GetTypeParamsOrArgsForGenericType(typeId, token);

                                if (genericTypeArgs.Count > 0)
                                {
                                    isTryingLinq = 1;
                                    methodId     = await context.SdbAgent.MakeGenericMethod(methodId, genericTypeArgs, token);

                                    break;
                                }
                            }
                        }
                    }
                    if (methodId == 0)
                    {
                        var typeName = await context.SdbAgent.GetTypeName(typeIds[0], token);

                        throw new Exception($"Method '{methodName}' not found in type '{typeName}'");
                    }
                    using var commandParamsObjWriter = new MonoBinaryWriter();
                    if (isTryingLinq == 0)
                    {
                        commandParamsObjWriter.WriteObj(objectId, context.SdbAgent);
                    }
                    if (method.ArgumentList != null)
                    {
                        commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count + isTryingLinq);
                        if (isTryingLinq == 1)
                        {
                            commandParamsObjWriter.WriteObj(objectId, context.SdbAgent);
                        }
                        foreach (var arg in method.ArgumentList.Arguments)
                        {
                            if (arg.Expression is LiteralExpressionSyntax)
                            {
                                if (!await commandParamsObjWriter.WriteConst(arg.Expression as LiteralExpressionSyntax, context.SdbAgent, token))
                                {
                                    return(null);
                                }
                            }
                            if (arg.Expression is IdentifierNameSyntax)
                            {
                                var argParm = arg.Expression as IdentifierNameSyntax;
                                if (!await commandParamsObjWriter.WriteJsonValue(memberAccessValues[argParm.Identifier.Text], context.SdbAgent, token))
                                {
                                    return(null);
                                }
                            }
                        }
                        var retMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), 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);
        }
        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)
                        {
                            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 context.SdbAgent.GetArrayValues(int.Parse(objectId.Value), token);

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

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

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

                            var commandParamsObjWriter = new MonoBinaryWriter();
                            commandParamsObjWriter.WriteObj(objectId, context.SdbAgent);
                            var toArrayRetMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, elementAccess.Expression.ToString(), token);

                            rootObject = await GetValueFromObject(toArrayRetMethod, token);

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

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

                        default:
                            throw new InvalidOperationException($"Cannot apply indexing with [] to an expression of type '{objectId.Scheme}'");
                        }
                    }
                }
                return(null);
            }
            catch (Exception ex)
            {
                var e = ex;
                throw new Exception($"Unable to evaluate method '{elementAccess}'");
            }
        }