示例#1
0
        /// <summary>
        /// Locates a bus by reference
        /// </summary>
        /// <returns>The bus.</returns>
        /// <param name="network">The top-level network.</param>
        /// <param name="proc">The process where the method is located.</param>
        /// <param name="method">The method the expression is found.</param>
        /// <param name="expression">The expression used to initialize the bus.</param>
        protected virtual Bus LocateBus(NetworkState network, ProcessState proc, MethodState method, ICSharpCode.Decompiler.CSharp.Syntax.Expression expression)
        {
            var de = TryLocateElement(network, proc, method, null, expression);

            if (de is AST.Bus)
            {
                return(de as AST.Bus);
            }

            throw new Exception("Need to walk the tree?");
        }
示例#2
0
        /// <summary>
        /// Locates the target for an expression.
        /// </summary>
        /// <returns>The data element.</returns>
        /// <param name="network">The top-level network.</param>
        /// <param name="proc">The process where the method is located.</param>
        /// <param name="method">The method where the statement is found.</param>
        /// <param name="statement">The statement where the expression is found.</param>
        /// <param name="expression">The expression to examine.</param>
        protected ASTItem TryLocateElement(NetworkState network, ProcessState proc, MethodState method, Statement statement, ICSharpCode.Decompiler.CSharp.Syntax.Expression expression)
        {
            if (expression is ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression)
            {
                var e      = expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression;
                var target = e.Target;
                return(LocateDataElement(network, proc, method, statement, target));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression)
            {
                var e      = expression as ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression;
                var target = e.Target;
                return(LocateDataElement(network, proc, method, statement, target));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)
            {
                var e    = expression as ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression;
                var name = e.Identifier;

                Variable variable;
                if (method != null && method.TryGetVariable(name, out variable))
                {
                    return(variable);
                }

                if (method != null)
                {
                    var p = method.Parameters.FirstOrDefault(x => x.Name == name);
                    if (p != null)
                    {
                        return(p);
                    }
                }

                if (proc.Variables.TryGetValue(name, out variable))
                {
                    return(variable);
                }

                Signal signal;
                if (proc != null && proc.Signals.TryGetValue(name, out signal))
                {
                    return(signal);
                }

                return(null);
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)
            {
                var e = expression as ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression;

                ASTItem current = null;

                var parts = new List <string>();
                ICSharpCode.Decompiler.CSharp.Syntax.Expression ec = e;
                while (ec != null)
                {
                    if (ec is ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)
                    {
                        parts.Add(((ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)ec).MemberName);
                        ec = ((ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)ec).Target;
                    }
                    else if (ec is ICSharpCode.Decompiler.CSharp.Syntax.ThisReferenceExpression)
                    {
                        //parts.Add("this");
                        ec = null;
                        break;
                    }
                    else if (ec is ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)
                    {
                        parts.Add(((ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)ec).Identifier);
                        ec = null;
                        break;
                    }
                    else if (ec is ICSharpCode.Decompiler.CSharp.Syntax.TypeReferenceExpression)
                    {
                        TypeDefinition dc = null;
                        if (method != null)
                        {
                            dc = method.SourceMethod.DeclaringType;
                        }
                        else if (proc != null)
                        {
                            dc = proc.CecilType.Resolve();
                        }

                        var ecs = ec.ToString();

                        if (dc != null)
                        {
                            if (ecs == dc.FullName || ecs == dc.Name)
                            {
                                ec = null;
                                //parts.Add("this");
                                break;
                            }

                            var targetproc = network.Processes.FirstOrDefault(x => x.CecilType.Name == ecs || x.CecilType.FullName == ecs);
                            if (targetproc != null)
                            {
                                // This is a static reference
                                current = null;                                 //targetproc;
                                break;
                            }

                            var bt = LoadTypeByName(ecs, dc.Module);
                            if (bt == null)
                            {
                                bt = LoadTypeByName(dc.FullName + "." + ecs, method.SourceMethod.Module);
                            }
                            if (bt == null)
                            {
                                bt = LoadTypeByName(dc.Namespace + "." + ecs, method.SourceMethod.Module);
                            }
                            // In some cases dc.Namespace is empty ...
                            if (bt == null && proc != null && proc.SourceType != null)
                            {
                                bt = LoadTypeByName(proc.SourceType.Namespace + "." + ecs, method.SourceMethod.Module);
                            }

                            if (bt != null && parts.Count == 1)
                            {
                                var br = bt.Resolve();
                                var px = br.Fields.FirstOrDefault(x => x.Name == parts[0]);

                                // Enum flags are encoded as constants
                                if (br.IsEnum)
                                {
                                    if (px == null)
                                    {
                                        throw new Exception($"Unable to find enum value {parts[0]} in {br.FullName}");
                                    }

                                    return(new Constant()
                                    {
                                        CecilType = bt,
                                        DefaultValue = px,
                                        Source = expression
                                    });
                                }
                                else
                                {
                                    // This is a constant of sorts
                                    var pe = network.ConstantLookup.Keys.FirstOrDefault(x => x.Name == parts[0]);
                                    if (pe != null)
                                    {
                                        return(network.ConstantLookup[pe]);
                                    }

                                    return(network.ConstantLookup[px] = new Constant()
                                    {
                                        CecilType = px.FieldType,
                                        Name = parts[0],
                                        Source = px,
                                        Parent = network
                                    });
                                }

                                //parts.AddRange(bt.FullName.Split('.').Reverse());
                            }


                            break;
                        }

                        // Likely a static reference, which is stored as a global constant
                        ec = null;
                    }
                    else
                    {
                        throw new Exception($"Unexpected element in reference chain: {ec.GetType().FullName}");
                    }
                }

                parts.Reverse();
                var fullname = string.Join(".", parts);


                if (parts.First() == "this")
                {
                    parts.RemoveAt(0);
                    if (proc == null)
                    {
                        throw new Exception("Attempting to do a resolve of \this\" but no process context is provided");
                    }
                    current = proc;
                }

                var first = true;
                foreach (var el in parts)
                {
                    var isIsFirst = first;
                    first = false;

                    if (current == null)
                    {
                        var pe = network.ConstantLookup.Keys.FirstOrDefault(x => x.Name == el);
                        if (pe != null)
                        {
                            current = network.ConstantLookup[pe];
                            continue;
                        }
                    }

                    if (current is MethodState || (isIsFirst && current == null))
                    {
                        //if (method.LocalRenames.ContainsKey(el))
                        //	el = method.LocalRenames[el];

                        var mt = current as MethodState ?? method;
                        if (mt != null)
                        {
                            Variable temp;
                            if (mt.TryGetVariable(el, out temp))
                            {
                                current = temp;
                                continue;
                            }

                            var p = mt.Parameters.FirstOrDefault(x => x.Name == el);
                            if (p != null)
                            {
                                current = p;
                                continue;
                            }

                            if (mt.ReturnVariable != null && !string.IsNullOrWhiteSpace(mt.ReturnVariable.Name) && el == mt.ReturnVariable.Name)
                            {
                                current = mt.ReturnVariable;
                                continue;
                            }
                        }
                    }

                    if (current is ProcessState || (isIsFirst && current == null))
                    {
                        var pr = current as ProcessState ?? proc;

                        if (pr != null)
                        {
                            if (pr.BusInstances.ContainsKey(el))
                            {
                                current = pr.BusInstances[el];
                                continue;
                            }

                            if (pr.Signals.ContainsKey(el))
                            {
                                current = pr.Signals[el];
                                continue;
                            }

                            if (pr.Variables.ContainsKey(el))
                            {
                                current = pr.Variables[el];
                                continue;
                            }

                            if (pr.Methods != null)
                            {
                                var p = pr.Methods.FirstOrDefault(x => x.Name == el);
                                if (p != null)
                                {
                                    current = p;
                                    continue;
                                }
                            }
                        }
                    }

                    if (current is Bus)
                    {
                        current = ((Bus)current).Signals.FirstOrDefault(x => x.Name == el);
                        if (current != null)
                        {
                            continue;
                        }
                    }

                    if (current is Variable)
                    {
                        var fi = ((Variable)current).CecilType.Resolve().Fields.FirstOrDefault(x => x.Name == el);
                        if (fi != null)
                        {
                            current = new Variable()
                            {
                                Name         = el,
                                Parent       = current,
                                Source       = fi,
                                CecilType    = fi.FieldType,
                                DefaultValue = null
                            };

                            continue;
                        }

                        var pi = ((Variable)current).CecilType.Resolve().Properties.FirstOrDefault(x => x.Name == el);
                        if (pi != null)
                        {
                            current = new Variable()
                            {
                                Name         = el,
                                Parent       = current,
                                Source       = fi,
                                CecilType    = fi.FieldType,
                                DefaultValue = null
                            };

                            continue;
                        }
                    }

                    if (el == "Length" && (current is DataElement) && ((DataElement)current).CecilType.IsArrayType())
                    {
                        return(new Constant()
                        {
                            ArrayLengthSource = current as DataElement,
                            CecilType = LoadType(typeof(int)),
                            DefaultValue = null,
                            Source = (current as DataElement).Source
                        });
                    }

                    throw new Exception($"Failed lookup at {el} in {fullname}");
                }

                if (current == null)
                {
                    throw new Exception($"Failed to fully resolve {fullname}");
                }

                return(current);
            }
            else
            {
                throw new Exception($"Unable to find a data element for an expression of type {expression.GetType().FullName}");
            }
        }
示例#3
0
        /// <summary>
        /// Locates the target for an expression, and throws an exception if not found.
        /// </summary>
        /// <returns>The data element.</returns>
        /// <param name="network">The top-level network.</param>
        /// <param name="proc">The process where the method is located.</param>
        /// <param name="method">The method where the statement is found.</param>
        /// <param name="statement">The statement where the expression is found.</param>
        /// <param name="expression">The expression to examine.</param>
        protected virtual DataElement LocateDataElement(NetworkState network, ProcessState proc, MethodState method, Statement statement, ICSharpCode.Decompiler.CSharp.Syntax.Expression expression)
        {
            var res = TryLocateDataElement(network, proc, method, statement, expression);

            if (res == null)
            {
                throw new Exception($"Unable to locate item for {expression}");
            }

            return(res);
        }
示例#4
0
        /// <summary>
        /// Locates the target for an expression.
        /// </summary>
        /// <returns>The data element.</returns>
        /// <param name="network">The top-level network.</param>
        /// <param name="proc">The process where the method is located.</param>
        /// <param name="method">The method where the statement is found.</param>
        /// <param name="statement">The statement where the expression is found.</param>
        /// <param name="expression">The expression to examine.</param>
        protected DataElement TryLocateDataElement(NetworkState network, ProcessState proc, MethodState method, Statement statement, ICSharpCode.Decompiler.CSharp.Syntax.Expression expression)
        {
            var el = TryLocateElement(network, proc, method, statement, expression);

            if (el == null)
            {
                return(null);
            }

            if (!(el is DataElement))
            {
                throw new Exception($"Failed to fully resolve {expression.ToString()}, got a result of type {el.GetType().FullName}");
            }

            return((DataElement)el);
        }
        /// <summary>
        /// Examines the given expression and returns the resulting output type from the expression
        /// </summary>
        /// <returns>The expression type.</returns>
        /// <param name="network">The top-level network.</param>
        /// <param name="proc">The process where the method is located.</param>
        /// <param name="method">The method where the statement is found.</param>
        /// <param name="statement">The statement where the expression is found.</param>
        /// <param name="expression">The expression to examine.</param>
        protected TypeReference ResolveExpressionType(NetworkState network, ProcessState proc, MethodState method, Statement statement, ICSharpCode.Decompiler.CSharp.Syntax.Expression expression)
        {
            if (expression is ICSharpCode.Decompiler.CSharp.Syntax.AssignmentExpression)
            {
                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.AssignmentExpression).Left));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)
            {
                return(LocateDataElement(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression).CecilType);
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)
            {
                var el = TryLocateElement(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression);
                if (el == null)
                {
                    throw new Exception($"Location failed for expression {expression}");
                }
                else if (el is DataElement)
                {
                    return(((DataElement)el).CecilType);
                }
                else if (el is Method)
                {
                    var rv = ((Method)el).ReturnVariable;
                    if (rv == null)
                    {
                        return(null);
                    }

                    return(rv.CecilType);
                }
                else
                {
                    throw new Exception($"Unexpected result for {expression} {el.GetType().FullName}");
                }
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.PrimitiveExpression)
            {
                return(LoadType((expression as ICSharpCode.Decompiler.CSharp.Syntax.PrimitiveExpression).Value.GetType()));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorExpression)
            {
                var e  = expression as ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorExpression;
                var op = e.Operator;
                if (op.IsCompareOperator() || op.IsLogicalOperator())
                {
                    return(LoadType(typeof(bool)));
                }



                var lefttype = ResolveExpressionType(network, proc, method, statement, e.Left);
                //var righttype = ResolveExpressionType(network, proc, method, statement, e.Right);

                if (op.IsArithmeticOperator() || op.IsBitwiseOperator())
                {
                    var righttype = ResolveExpressionType(network, proc, method, statement, e.Right);

                    // Custom resolve of the resulting type as dictated by the .Net rules
                    if (righttype.IsSameTypeReference <double>() || lefttype.IsSameTypeReference <double>())
                    {
                        return(lefttype.LoadType(typeof(double)));
                    }
                    if (righttype.IsSameTypeReference <float>() || lefttype.IsSameTypeReference <float>())
                    {
                        return(lefttype.LoadType(typeof(float)));
                    }
                    if (righttype.IsSameTypeReference <ulong>() || lefttype.IsSameTypeReference <ulong>())
                    {
                        return(lefttype.LoadType(typeof(ulong)));
                    }
                    if (righttype.IsSameTypeReference <long>() || lefttype.IsSameTypeReference <long>())
                    {
                        return(lefttype.LoadType(typeof(long)));
                    }

                    if (righttype.IsSameTypeReference <uint>() || lefttype.IsSameTypeReference <uint>())
                    {
                        if (lefttype.IsSameTypeReference <sbyte>() || lefttype.IsSameTypeReference <short>() || righttype.IsSameTypeReference <sbyte>() || righttype.IsSameTypeReference <short>())
                        {
                            return(lefttype.LoadType(typeof(long)));
                        }
                        else
                        {
                            return(lefttype.LoadType(typeof(uint)));
                        }
                    }

                    if (righttype.IsSameTypeReference <int>() || lefttype.IsSameTypeReference <int>())
                    {
                        if (righttype.IsSameTypeReference <uint>() || lefttype.IsSameTypeReference <uint>())
                        {
                            return(lefttype.LoadType(typeof(uint)));
                        }
                        else
                        {
                            return(lefttype.LoadType(typeof(int)));
                        }
                    }

                    if (righttype.IsSameTypeReference <ushort>() || lefttype.IsSameTypeReference <ushort>())
                    {
                        return(lefttype.LoadType(typeof(int)));
                    }
                    if (righttype.IsSameTypeReference <short>() || lefttype.IsSameTypeReference <short>())
                    {
                        return(lefttype.LoadType(typeof(int)));
                    }
                    if (righttype.IsSameTypeReference <sbyte>() || lefttype.IsSameTypeReference <sbyte>())
                    {
                        return(lefttype.LoadType(typeof(int)));
                    }
                    if (righttype.IsSameTypeReference <byte>() || lefttype.IsSameTypeReference <byte>())
                    {
                        return(lefttype.LoadType(typeof(int)));
                    }


                    Console.WriteLine("Warning: unable to determine result type for operation {0} on types {1} and {2}", op, lefttype, righttype);
                    //TODO: Return a larger type, double the bits?
                    return(lefttype);
                }
                else
                {
                    // TODO: Find the largest type?
                    return(lefttype);
                }
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression)
            {
                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression).Expression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression)
            {
                var arraytype = ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression).Target);
                return(arraytype.GetArrayElementType());
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.CastExpression)
            {
                return(LoadType((expression as ICSharpCode.Decompiler.CSharp.Syntax.CastExpression).Type, method));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.ConditionalExpression)
            {
                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.ConditionalExpression).TrueExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression)
            {
                var si = expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression;
                var mt = si.Target as ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression;

                // Catch common translations
                if (mt != null && (expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression).Arguments.Count == 1)
                {
                    if (mt.MemberName == "op_Implicit" || mt.MemberName == "op_Explicit")
                    {
                        var mtm = Decompile(network, proc, method, statement, mt);
                        return(ResolveExpressionType(network, proc, method, statement, new ICSharpCode.Decompiler.CSharp.Syntax.CastExpression(ICSharpCode.Decompiler.CSharp.Syntax.AstType.Create(mtm.SourceResultType.FullName), si.Arguments.First().Clone())));
                    }
                    else if (mt.MemberName == "op_Increment")
                    {
                        return(ResolveExpressionType(network, proc, method, statement, new ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression(ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.Increment, si.Arguments.First().Clone())));
                    }
                    else if (mt.MemberName == "op_Decrement")
                    {
                        return(ResolveExpressionType(network, proc, method, statement, new ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression(ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.Decrement, si.Arguments.First().Clone())));
                    }
                }

                var m = proc.CecilType.Resolve().GetMethods().FirstOrDefault(x => x.Name == mt.MemberName);
                if (m != null)
                {
                    return(m.ReturnType);
                }

                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression).Target));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.ParenthesizedExpression)
            {
                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.ParenthesizedExpression).Expression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.NullReferenceExpression)
            {
                return(null);
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.ArrayCreateExpression)
            {
                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.ArrayCreateExpression).Initializer.FirstChild as ICSharpCode.Decompiler.CSharp.Syntax.Expression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.CheckedExpression)
            {
                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.CheckedExpression).Expression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.UncheckedExpression)
            {
                return(ResolveExpressionType(network, proc, method, statement, (expression as ICSharpCode.Decompiler.CSharp.Syntax.UncheckedExpression).Expression));
            }
            else if (expression == ICSharpCode.Decompiler.CSharp.Syntax.Expression.Null)
            {
                return(null);
            }
            else
            {
                throw new Exception(string.Format("Unsupported expression: {0} ({1})", expression, expression.GetType().FullName));
            }
        }