Example #1
0
        public void Read(MethodBody body, InstructionMapper mapper)
        {
            var method_token = body.Method.MetadataToken;

            PdbFunction function;

            if (!functions.TryGetValue(method_token.ToUInt32(), out function))
            {
                return;
            }

            ReadSequencePoints(function, mapper);
            ReadScopeAndLocals(function.scopes, null, body, mapper);

            if (!string.IsNullOrEmpty(function.iteratorClass))
            {
                body.IteratorType = body.Method.DeclaringType.GetNestedType(function.iteratorClass);
            }

            if (function.iteratorScopes != null)
            {
                foreach (Microsoft.Cci.ILocalScope scope in function.iteratorScopes)
                {
                    InstructionRange range = new InstructionRange();
                    SetInstructionRange(body, mapper, range, scope.Offset, scope.Length);
                    body.IteratorScopes.Add(range);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Convert the given set of bytecodes into a list of Ast nodes.
        /// </summary>
        private static IEnumerable <AstNode> ConvertRangeToAst(IEnumerable <ByteCode> range)
        {
            var ast = new List <AstNode>();

            // Convert stack-based java bytecode code to Ast tree
            foreach (var byteCode in range)
            {
                var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset);
                if (byteCode.StackBefore == null)
                {
                    // Unreachable code
                    continue;
                }

                var expr = new AstExpression(byteCode.SourceLocation, byteCode.Code, byteCode.Operand);
                expr.ILRanges.Add(ilRange);

                // Label for this instruction
                if (byteCode.Label(false) != null)
                {
                    ast.Add(byteCode.Label(false));
                }

                // Reference arguments using temporary variables
                var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
                for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++)
                {
                    var slot = byteCode.StackBefore[i];
                    expr.Arguments.Add(new AstExpression(byteCode.SourceLocation, AstCode.Ldloc, slot.LoadFrom));
                }

                // Store the result to temporary variable(s) if needed
                if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0)
                {
                    ast.Add(expr);
                }
                else if (byteCode.StoreTo.Count == 1)
                {
                    ast.Add(new AstExpression(byteCode.SourceLocation, AstCode.Stloc, byteCode.StoreTo[0], expr));
                }
                else
                {
                    var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault());
                    ast.Add(new AstExpression(byteCode.SourceLocation, AstCode.Stloc, tmpVar, expr));
                    foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse())
                    {
                        ast.Add(new AstExpression(byteCode.SourceLocation, AstCode.Stloc, storeTo, new AstExpression(byteCode.SourceLocation, AstCode.Ldloc, tmpVar)));
                    }
                }
            }

            return(ast);
        }
Example #3
0
        static void SetInstructionRange(MethodBody body, InstructionMapper mapper, InstructionRange range, uint offset, uint length)
        {
            range.Start = mapper((int)offset);
            range.End   = mapper((int)(offset + length));

            if (range.End == null)
            {
                range.End = body.Instructions[body.Instructions.Count - 1];
            }
            else
            {
                range.End = range.End.Previous;
            }

            if (range.Start == null)
            {
                range.Start = range.End;
            }
        }
Example #4
0
        private List<AstNode> ConvertToAst(IEnumerable<ByteCode> body)
        {
            var ast = new List<AstNode>();

            // Convert stack-based IL code to ILAst tree
            foreach (var byteCode in body)
            {
                var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset);

                if (byteCode.StackBefore == null)
                {
                    // Unreachable code
                    continue;
                }

                var expr = new AstExpression(byteCode.SequencePoint, byteCode.Code, byteCode.Operand);
                expr.ILRanges.Add(ilRange);
                if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0)
                {
                    var prefixes = new AstExpressionPrefix[byteCode.Prefixes.Length];
                    for (var i = 0; i < prefixes.Length; i++)
                    {
                        var operand = byteCode.Prefixes[i].Operand;
                        if (operand is FieldReference)
                        {
                            operand = XBuilder.AsFieldReference(module, (FieldReference) operand);
                        }
                        else if (operand is MethodReference)
                        {
                            operand = XBuilder.AsMethodReference(module, (MethodReference)operand);
                        }
                        else if (operand is TypeReference)
                        {
                            operand = XBuilder.AsTypeReference(module, (TypeReference) operand);
                        }
                        prefixes[i] = new AstExpressionPrefix((AstCode)byteCode.Prefixes[i].OpCode.Code, operand);
                    }
                    expr.Prefixes = prefixes;
                }

                // Label for this instruction
                if (byteCode.Label != null)
                {
                    ast.Add(byteCode.Label);
                }

                // Reference arguments using temporary variables
                var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
                for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++)
                {
                    var slot = byteCode.StackBefore[i];
                    expr.Arguments.Add(new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, slot.LoadFrom));
                }

                // Store the result to temporary variable(s) if needed
                if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0)
                {
                    ast.Add(expr);
                }
                else if (byteCode.StoreTo.Count == 1)
                {
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, byteCode.StoreTo[0], expr));
                }
                else
                {
                    var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault());
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, tmpVar, expr));
                    foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse())
                    {
                        ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, storeTo, new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, tmpVar)));
                    }
                }
            }

            return ast;
        }
Example #5
0
        void InventoryPage_draw()
        {
            // Change the equipment slot drawing code to draw the 4 additional slots.
            InstructionRange range = null;

            try {
                range = FindCode(
                    // switch (equipmentIcon.name) {
                    Instructions.Ldloca_S(3),
                    OpCodes.Call,
                    Instructions.Stloc_S(4),
                    Instructions.Ldloc_S(4),
                    Instructions.Ldfld(typeof(ClickableComponent), nameof(ClickableComponent.name)),
                    Instructions.Stloc_S(5),
                    Instructions.Ldloc_S(5),
                    // case "Hat":
                    Instructions.Ldstr("Hat")
                    );
            } catch (System.Exception err) {
                LogException(err, LogLevel.Trace);
                range = FindCode(
                    // switch (equipmentIcon.name) {
                    Instructions.Ldloca_S(1),
                    OpCodes.Call,
                    Instructions.Stloc_0(),
                    Instructions.Ldloc_0(),
                    Instructions.Ldfld(typeof(ClickableComponent), nameof(ClickableComponent.name)),
                    Instructions.Stloc_2(),
                    Instructions.Ldloc_2(),
                    // case null (shortcut)
                    OpCodes.Brfalse,
                    Instructions.Ldloc_2(),
                    // case "Hat":
                    Instructions.Ldstr("Hat")
                    );
            }
            if (range.length != 8 && range.length != 10)
            {
                throw new System.Exception($"Failed to properly match code. Length={range.length}");
            }

            range.Extend(range.Follow(-1));
            range.Replace(
                range[0],
                range[1],
                Instructions.Ldarg_1(),
                Instructions.Call(typeof(ModEntry), nameof(DrawEquipment), typeof(ClickableComponent), typeof(Microsoft.Xna.Framework.Graphics.SpriteBatch))
                );

            // Move other stuff 32/64px to the right to eliminate overlap.
            for (int i = 0; i < 11; i++)
            {
                range = range.FindNext(
                    OpCodes.Ldarg_0,
                    Instructions.Ldfld(typeof(IClickableMenu), nameof(IClickableMenu.xPositionOnScreen)),
                    OpCodes.Ldc_I4,
                    OpCodes.Add
                    );
                int val = (int)range[2].operand + 32;
                if (val < 256)
                {
                    val = 256;
                }
                range[2].operand = val;
            }
        }
Example #6
0
        private List <AstNode> ConvertToAst(IEnumerable <ByteCode> body)
        {
            var ast = new List <AstNode>();

            // Convert stack-based IL code to ILAst tree
            foreach (var byteCode in body)
            {
                var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset);

                if (byteCode.StackBefore == null)
                {
                    // Unreachable code
                    continue;
                }

                var expr = new AstExpression(byteCode.SequencePoint, byteCode.Code, byteCode.Operand);
                expr.ILRanges.Add(ilRange);
                if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0)
                {
                    var prefixes = new AstExpressionPrefix[byteCode.Prefixes.Length];
                    for (var i = 0; i < prefixes.Length; i++)
                    {
                        var operand = byteCode.Prefixes[i].Operand;
                        if (operand is FieldReference)
                        {
                            operand = XBuilder.AsFieldReference(module, (FieldReference)operand);
                        }
                        else if (operand is MethodReference)
                        {
                            operand = XBuilder.AsMethodReference(module, (MethodReference)operand);
                        }
                        else if (operand is TypeReference)
                        {
                            operand = XBuilder.AsTypeReference(module, (TypeReference)operand);
                        }
                        prefixes[i] = new AstExpressionPrefix((AstCode)byteCode.Prefixes[i].OpCode.Code, operand);
                    }
                    expr.Prefixes = prefixes;
                }

                // Label for this instruction
                if (byteCode.Label != null)
                {
                    ast.Add(byteCode.Label);
                }

                // Reference arguments using temporary variables
                var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
                for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++)
                {
                    var slot = byteCode.StackBefore[i];
                    expr.Arguments.Add(new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, slot.LoadFrom));
                }

                // Store the result to temporary variable(s) if needed
                if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0)
                {
                    ast.Add(expr);
                }
                else if (byteCode.StoreTo.Count == 1)
                {
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, byteCode.StoreTo[0], expr));
                }
                else
                {
                    var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault());
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, tmpVar, expr));
                    foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse())
                    {
                        ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, storeTo, new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, tmpVar)));
                    }
                }
            }

            return(ast);
        }