예제 #1
0
 public override Statement CloneStatementOnly()
 {
     BlockStatement result = new BlockStatement();
     CopyParentAndLabel(result);
     foreach (Statement s in statements)
     {
         result.AddStatement(s.CloneStatementOnly());
     }
     return result;
 }
예제 #2
0
        public override Statement CloneStatementOnly()
        {
            BlockStatement result = new BlockStatement();

            CopyParentAndLabel(result);
            foreach (Statement s in statements)
            {
                result.AddStatement(s.CloneStatementOnly());
            }
            return(result);
        }
		public BlockStatement Process(DecompilationContext context, BlockStatement body)
		{
			MethodDefinition method = context.MethodContext.Method;

			if (!method.IsUnsafe && method.HasBody && IsUnsafe(method.Body.Instructions))
			{
				UnsafeBlockStatement unsafeStatement = new UnsafeBlockStatement(body.Statements);
				body.Statements = new StatementCollection();
				body.AddStatement(unsafeStatement);
			}

			return body;
		}
예제 #4
0
 public override Statement Clone()
 {
     V_0 = new BlockStatement();
     this.CopyParentAndLabel(V_0);
     V_1 = this.statements.GetEnumerator();
     try
     {
         while (V_1.MoveNext())
         {
             V_2 = V_1.get_Current();
             V_0.AddStatement(V_2.Clone());
         }
     }
     finally
     {
         if (V_1 != null)
         {
             V_1.Dispose();
         }
     }
     return(V_0);
 }
        private ICodeNode ConvertLambda(MethodInvocationExpression invocation)
        {
            if (invocation.Arguments.Count != 2)
            {
                return null;
            }

            ArrayCreationExpression arguments = Visit(invocation.Arguments[1]) as ArrayCreationExpression;
            if (arguments == null || arguments.Initializer == null || arguments.Initializer.Expressions == null ||
                arguments.Initializer.Expressions.Any(element => element.CodeNodeType != CodeNodeType.ArgumentReferenceExpression))
            {
                return null;
            }

            List<ArgumentReferenceExpression> parameters = arguments.Initializer.Expressions.Cast<ArgumentReferenceExpression>().ToList();

            bool hasAnonymousParameter = parameters.Any(param => param.Parameter.ParameterType.Resolve().IsAnonymous());

            BlockStatement body = new BlockStatement();
            body.AddStatement(new ExpressionStatement(new ShortFormReturnExpression((Expression)Visit(invocation.Arguments[0]), null)));

            return new LambdaExpression(new ExpressionCollection(parameters.Select(param => new LambdaParameterExpression(param.Parameter, !hasAnonymousParameter, null))),
                body, false, false, parameters.Select(argRef => argRef.Parameter), true, null);
        }
        private CachedDecompiledMember DecompileMethod(ILanguage language, MethodDefinition method, TypeSpecificContext typeContext)
        {
            CachedDecompiledMember decompiledMember;
            Statement statement;
            try
            {
                DecompilationContext innerContext = null;
                statement = method.Body.Decompile(language, out innerContext, typeContext);
                decompiledMember = new CachedDecompiledMember(new DecompiledMember(Utilities.GetMemberUniqueName(method), statement, innerContext.MethodContext), innerContext.TypeContext);
            }
            catch (Exception ex)
            {
                this.ExceptionsWhileDecompiling.Add(method);

                BlockStatement blockStatement = new BlockStatement();
                statement = new ExceptionStatement(ex, method);
                blockStatement.AddStatement(statement);

                decompiledMember = new CachedDecompiledMember(new DecompiledMember(Utilities.GetMemberUniqueName(method), blockStatement, new MethodSpecificContext(method.Body)));
            }
            return decompiledMember;
        }
        /// <summary>
        /// Performs a move out operation on the goto statement. For more information see
        /// Chapter 2.2.1 "Outward-movement Transformations"
        /// </summary>
        /// <param name="gotoStatement"></param>
        /// <param name="label"></param>
        private void MoveOut(IfStatement gotoStatement, string label)
        {
            /// Preprocessing.
            BlockStatement containingBlock = gotoStatement.Parent as BlockStatement;
            BlockStatement outerBlock = GetOuterBlock(containingBlock);
            VariableReferenceExpression conditionVar = new VariableReferenceExpression(GetLabelVariable(label), null);

            ExtractConditionIntoVariable(conditionVar.CloneExpressionOnly() as VariableReferenceExpression, gotoStatement, containingBlock);

            Statement oldEnclosingStatement = containingBlock.Parent;
            if (oldEnclosingStatement is SwitchCase)
            {
                oldEnclosingStatement = oldEnclosingStatement.Parent;
            }
            if (containingBlock.Parent is SwitchCase || containingBlock.Parent is WhileStatement || containingBlock.Parent is DoWhileStatement || containingBlock.Parent is ForStatement
                || containingBlock.Parent is ForEachStatement)
            {
                /// Then we can exit using break.
                /// Create the if - break.
                BlockStatement thenBlock = new BlockStatement();
                thenBlock.AddStatement(new BreakStatement(null));  //might have to keep track of brakes
                IfStatement breakIf = new IfStatement(conditionVar.CloneExpressionOnly(), thenBlock, null);

                /// Replace the original goto
                int gotoIndex = containingBlock.Statements.IndexOf(gotoStatement);
                containingBlock.Statements.Remove(gotoStatement);
                containingBlock.AddStatementAt(gotoIndex, breakIf);
            }
            else if (containingBlock.Parent is IfStatement || containingBlock.Parent is TryStatement || containingBlock.Parent is IfElseIfStatement)
            {
                /// Then we can exit via introducing another condition.
                int gotoIndex = containingBlock.Statements.IndexOf(gotoStatement);
                int index = gotoIndex + 1;
                BlockStatement thenBlock = new BlockStatement();
                while (index < containingBlock.Statements.Count)
                {
                    thenBlock.AddStatement(containingBlock.Statements[index]);
                    containingBlock.Statements.RemoveAt(index);
                }
                UnaryExpression condition = new UnaryExpression(UnaryOperator.LogicalNot, conditionVar.CloneExpressionOnly(), null);
                IfStatement innerIf = new IfStatement(condition, thenBlock, null);

                /// At this point the goto statement should be the last one in the block.
                /// Simply replace it with the new if.
                containingBlock.Statements.Remove(gotoStatement);
                /// If the then block is empty, the if should not be added.
                if (innerIf.Then.Statements.Count != 0)
                {
                    containingBlock.AddStatement(innerIf);
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException("Goto statement can not leave this parent construct.");
            }

            /// Add the goto statement after the construct.
            /// The goto statement shoud be detached from the AST at this point.
            outerBlock.AddStatementAt(outerBlock.Statements.IndexOf(oldEnclosingStatement) + 1, gotoStatement);
        }
        /// <summary>
        /// Contains the logic for moving a  goto inside the case of switch statement. For more information 
        /// see Chapter "2.2.2 Inward-movement Transformations : Moving a goto into a switch statement" from
        /// <see cref="Taming Control Flow A Structured Approach to Eliminating Goto Statements.pdf"/>.
        /// </summary>
        /// <param name="gotoStatement">The goto statement to be moved in.</param>
        /// <param name="switchCase">The switch case that contains the target of the goto statement.</param>
        /// <param name="label">The label of the target.</param>
        private void MoveInCase(IfStatement gotoStatement, SwitchCase switchCase, string label)
        {
            VariableReferenceExpression conditionVariable = new VariableReferenceExpression(GetLabelVariable(label), null);
            BlockStatement containingBlock = GetOuterBlock(gotoStatement);
            SwitchStatement switchStatement = switchCase.Parent as SwitchStatement;

            int gotoIndex = containingBlock.Statements.IndexOf(gotoStatement);
            int switchIndex = containingBlock.Statements.IndexOf(switchStatement);

            /// Generate variable and extract the switch condition
            string switchVariableName = "switch" + switchStatement.ConditionBlock.First.Offset;
            TypeReference switchVariableType = GetSwitchType(switchStatement);
            VariableDefinition switchVariable = new VariableDefinition(switchVariableName, switchVariableType);
            switchVariables.Add(switchVariable);
            VariableReferenceExpression switchVarEx = new VariableReferenceExpression(switchVariable, null);
            ExtractConditionIntoVariable(switchVarEx, switchStatement, containingBlock);

            BlockStatement thenBlock = CollectStatements(gotoIndex + 1, switchIndex + 1, containingBlock);

            BlockStatement elseBlock = new BlockStatement();

            /// Adds swCond = caseCond; in the last part of else.
            BinaryExpression assignSwitchVariable = new BinaryExpression(BinaryOperator.Assign, switchVarEx.CloneExpressionOnly(), GetCaseConditionExpression(switchCase), typeSystem, null);
            elseBlock.AddStatement(new ExpressionStatement(assignSwitchVariable));

            IfStatement precedingIf = new IfStatement(new UnaryExpression(UnaryOperator.LogicalNot, conditionVariable, null), thenBlock, elseBlock);

            /// Attach new if and move the goto conditional.
            /// Attach it only if the then block is not empty.
            if (precedingIf.Then.Statements.Count != 0)
            {
                containingBlock.AddStatementAt(gotoIndex, precedingIf);
            }
            containingBlock.Statements.Remove(gotoStatement);
            switchCase.Body.AddStatementAt(0, gotoStatement);
        }
        /// <summary>
        /// Embeds unconditional goto into <code> if(true){} </code> statement
        /// </summary>
        /// <param name="jump">The unconditional goto.</param>
        private void EmbedIntoDefaultIf(GotoStatement jump)
        {
            BlockStatement parentBlock = jump.Parent as BlockStatement;
            BlockStatement thenBlock = new BlockStatement();
            thenBlock.AddStatement(jump);
            Expression condition = GetLiteralExpression(true);
            IfStatement embeddingStatement = new IfStatement(condition, thenBlock, null);

            ///Should be initialized by the statements themselves, but just in case.
            thenBlock.Parent = embeddingStatement;

            ///Replace the old goto statement with the new embedding If
            int jumpIndex = parentBlock.Statements.IndexOf(jump);
            parentBlock.Statements.RemoveAt(jumpIndex);
            parentBlock.AddStatementAt(jumpIndex, embeddingStatement);

            if (parentBlock.Parent is ConditionCase)
            {
                ///If the goto was the last statement in case add break after the embedding if.
                int embeddingStatementIndex = parentBlock.Statements.IndexOf(embeddingStatement);
                if (embeddingStatementIndex == parentBlock.Statements.Count)
                {
                    parentBlock.AddStatement(new BreakStatement(null));
                }
            }
        }
        /// <summary>
        /// Inserts the selected statements into new BlockStatement and returns it. In the process the collected statements are detached from their previous containing block.
        /// </summary>
        /// <param name="startingIndex">The index of the first statement to be selected.</param>
        /// <param name="endingIndex">The index of the last statement. This is the first one that doesn't get selected.</param>
        /// <param name="containingBlock">The block from which statements are retrieved.</param>
        /// <returns>The new block containining the selected statements.</returns>
        private BlockStatement CollectStatements(int startingIndex, int endingIndex, BlockStatement containingBlock)
        {
            BlockStatement newThenBlock = new BlockStatement();

            for (int i = startingIndex; i < endingIndex; endingIndex--)
            {
                newThenBlock.AddStatement(containingBlock.Statements[i]);
                containingBlock.Statements.RemoveAt(i);
            }
            return newThenBlock;
        }
 /// <summary>
 /// Adds 
 /// <code>
 /// If(<paramref name="conditionVariable"/>)
 /// {
 ///     <paramref name="statement"/>
 /// }
 /// </code>
 /// statement at <paramref name="index"/> in <paramref name="containingBlock"/>
 /// </summary>
 /// <param name="index">The index at which the generated statement must be inserted.</param>
 /// <param name="containingBlock">The block, in which the new statement is inserted.</param>
 /// <param name="statement">The only statement in the then clause.</param>
 /// <param name="conditionVariable">The condition of the if.</param>
 private void AddBreakContinueConditional(int index, BlockStatement containingBlock, Statement statement, VariableReference conditionVariable)
 {
     BlockStatement thenBlock = new BlockStatement();
     thenBlock.AddStatement(statement);
     VariableReferenceExpression ifCondition = new VariableReferenceExpression(conditionVariable, null);
     IfStatement enclosingIfStatement = new IfStatement(ifCondition, thenBlock, null);
     containingBlock.AddStatementAt(index, enclosingIfStatement);
 }
        private BlockStatement FinishDecompilationOfMethod(BlockStatement block, DecompilationContext context, out MethodSpecificContext methodContext)
        {
            methodContext = null;

            BlockStatement fullyDecompiledBlock;
            try
            {
                BlockDecompilationPipeline pipeline = this.language.CreatePropertyPipeline(context);

                methodContext = pipeline.Run(context.MethodContext.Method.Body, block, this.language).MethodContext;

                fullyDecompiledBlock = pipeline.Body;
            }
            catch (Exception ex)
            {
                this.ExceptionsWhileDecompiling.Add(context.MethodContext.Method);

                methodContext = new MethodSpecificContext(context.MethodContext.Method.Body);

                fullyDecompiledBlock = new BlockStatement();
                fullyDecompiledBlock.AddStatement(new ExceptionStatement(ex, context.MethodContext.Method));

                OnExceptionThrown(ex);
            }

            return fullyDecompiledBlock;
        }
        private BlockStatement DecompileMethodPartially(MethodBody body, out DecompilationContext context, bool needDecompiledMember = false)
        {
            context = null;

            if (this.IsCachingEnabled && this.cacheService.IsDecompiledMemberInCache(body.Method, this.language, this.renameInvalidMembers))
            {
                CachedDecompiledMember cachedDecompiledMember = this.cacheService.GetDecompiledMemberFromCache(body.Method, this.language, this.renameInvalidMembers);
                return cachedDecompiledMember.Member.Statement as BlockStatement;
            }

            //Performance improvement
            ControlFlowGraph cfg = new ControlFlowGraphBuilder(body.Method).CreateGraph();
            if (cfg.Blocks.Length > 2)
            {
                return null;
            }

            BlockStatement block;
            try
            {
                DecompilationPipeline pipeline;
                DecompilationContext decompilationContext =
                    new DecompilationContext(new MethodSpecificContext(body), this.typeContext ?? new TypeSpecificContext(body.Method.DeclaringType), this.language);
                if (!needDecompiledMember)
                {
                    decompilationContext.MethodContext.EnableEventAnalysis = false;
                }

                pipeline = new DecompilationPipeline(BaseLanguage.IntermediateRepresenationPipeline.Steps, decompilationContext);

                context = pipeline.Run(body, this.language);

                block = pipeline.Body;
            }
            catch (Exception ex)
            {
                this.ExceptionsWhileDecompiling.Add(body.Method);

                block = new BlockStatement();
                block.AddStatement(new ExceptionStatement(ex, body.Method));

                OnExceptionThrown(ex);
            }

            return block;
        }
        private BlockStatement DecompileMethod(MethodBody body, out MethodSpecificContext methodContext)
        {
            methodContext = null;

            BlockStatement block;
            try
            {
                DecompilationContext decompilationContext =
                    new DecompilationContext(new MethodSpecificContext(body), this.typeContext ?? new TypeSpecificContext(body.Method.DeclaringType), this.language);

                DecompilationPipeline pipeline = this.language.CreatePipeline(decompilationContext);

                methodContext = pipeline.Run(body, this.language).MethodContext;

                block = pipeline.Body;
            }
            catch (Exception ex)
            {
                this.ExceptionsWhileDecompiling.Add(body.Method);

                methodContext = new MethodSpecificContext(body);

                block = new BlockStatement();
                block.AddStatement(new ExceptionStatement(ex, body.Method));

                OnExceptionThrown(ex);
            }

            return block;
        }
			private void CopyWhileBodyStatements(WhileStatement whileStatement)
			{
				statementBody = new BlockStatement();
				for (int i = 1; i < whileStatement.Body.Statements.Count - 1; i++)
				{
					statementBody.AddStatement(whileStatement.Body.Statements[i]);
				}
			}