Exemplo n.º 1
0
        /// <summary>
        /// Tries to get the state to which the current block leads.
        /// </summary>
        /// <remarks>
        /// We are searching for this pattern at the end of the block:
        /// .....
        /// load currentItemValue
        /// stfld currentItemField
        /// ldarg.0   --this
        /// ldc.i4. nextStateNumber
        /// stfld stateField
        /// .....
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <param name="newStateNumber"></param>
        /// <returns></returns>
        private NextStateNumberSearchResult TryGetNextStateNumber(InstructionBlock theBlock, out int newStateNumber)
        {
            Instruction currentInstruction = theBlock.Last;

            while (currentInstruction != theBlock.First)
            {
                if (currentInstruction.OpCode.Code == Code.Stfld && stateField == ((FieldReference)currentInstruction.Operand).Resolve())
                {
                    currentInstruction = currentInstruction.Previous;
                    if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out newStateNumber))
                    {
                        return(NextStateNumberSearchResult.PatternFailed);
                    }

                    //currentInstruction == ldc.i4. ; currentInstruction.Previous == ldarg.0 ; currentInstruction.Previous.Previous == stfld currentItemField
                    currentInstruction = currentInstruction.Previous.Previous;
                    if (currentInstruction.OpCode.Code != Code.Stfld || !CheckAndSaveCurrentItemField((FieldReference)currentInstruction.Operand))
                    {
                        return(NextStateNumberSearchResult.PatternFailed);
                    }

                    return(NextStateNumberSearchResult.StateNumberFound);
                }

                currentInstruction = currentInstruction.Previous;
            }

            newStateNumber = 0;
            return(NextStateNumberSearchResult.StateWasNotSet);
        }
        /// <summary>
        /// Checks whether the specified block is a state controller block generated by the C# compiler in debug mode.
        /// </summary>
        /// <remarks>
        /// Pattern:
        /// ldc.i4.1
        /// stloc* doFinallyVariable
        /// ldarg.0
        /// ldfld stateField
        /// ...
        /// ldc.i4.s -3
        /// (sub) - missing if next is beq*
        /// switch || beq*
        ///
        /// There is only one such block generated at the begining of the MoveNext method.
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <returns></returns>
        private bool IsDebugCheckStateBlock(InstructionBlock theBlock)
        {
            if (!BeginsWithDoFinallySet(theBlock) || !ContainsStateFieldLoad(theBlock))
            {
                return(false);
            }

            Instruction currentInstruction = theBlock.Last;

            if (!this.IsBeqInstruction(currentInstruction))
            {
                if (currentInstruction.OpCode.Code != Code.Switch)
                {
                    return(false);
                }

                currentInstruction = currentInstruction.Previous;
                if (currentInstruction.OpCode.Code != Code.Sub)
                {
                    return(false);
                }
            }

            currentInstruction = currentInstruction.Previous;
            int operand;

            if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out operand) || operand > -3)
            {
                return(false);
            }

            debugStateCheckBlock = theBlock;
            stateCheckOffset     = -operand;
            return(true);
        }
Exemplo n.º 3
0
 private bool DetermineExceptionHandlingStatesFromSwitchData(SwitchData switchBlockInfo)
 {
     V_0 = 0;
     V_1 = switchBlockInfo.get_SwitchBlock().get_Last().get_Previous();
     if (V_1.get_OpCode().get_Code() == 88)
     {
         V_1 = V_1.get_Previous();
         if (!StateMachineUtilities.TryGetOperandOfLdc(V_1, out V_0))
         {
             return(false);
         }
         V_1 = V_1.get_Previous();
     }
     V_2 = switchBlockInfo.get_OrderedCasesArray();
     V_4 = 0;
     while (V_4 < (int)V_2.Length)
     {
         if (this.TryGetExceptionHandler(this.GetActualCase(V_2[V_4]), out V_6))
         {
             if (!this.handlerToStatesMap.ContainsKey(V_6))
             {
                 this.handlerToStatesMap.Add(V_6, new HashSet <int>());
             }
             dummyVar0 = this.handlerToStatesMap.get_Item(V_6).Add(V_4 + V_0);
         }
         V_4 = V_4 + 1;
     }
     return(true);
 }
Exemplo n.º 4
0
 private bool IsDebugCheckStateBlock(InstructionBlock theBlock)
 {
     if (!this.BeginsWithDoFinallySet(theBlock) || !this.ContainsStateFieldLoad(theBlock))
     {
         return(false);
     }
     V_0 = theBlock.get_Last();
     if (!this.IsBeqInstruction(V_0))
     {
         if (V_0.get_OpCode().get_Code() != 68)
         {
             return(false);
         }
         V_0 = V_0.get_Previous();
         if (V_0.get_OpCode().get_Code() != 88)
         {
             return(false);
         }
     }
     V_0 = V_0.get_Previous();
     if (!StateMachineUtilities.TryGetOperandOfLdc(V_0, out V_1) || V_1 > -3)
     {
         return(false);
     }
     this.debugStateCheckBlock = theBlock;
     this.stateCheckOffset     = -V_1;
     return(true);
 }
Exemplo n.º 5
0
        /// <summary>
        /// Marks the predecessors, of the specifed instruction block, that set the return flag variable to true, as yield returns.
        /// </summary>
        /// <remarks>
        /// If a predecessor is a block that contains a single unconditional branch instruction then we recursively call the method for that
        /// predecessor and we mark it for removal.
        /// This means that the block, that we initially call this method for, will not be removed and will be left to be marked as an yield break.
        /// </remarks>
        /// <param name="theBlock"></param>
        private bool MarkTrueReturningPredecessorsAsYieldReturn(InstructionBlock theBlock)
        {
            HashSet <InstructionBlock> predecessors = new HashSet <InstructionBlock>(theBlock.Predecessors);

            foreach (InstructionBlock predecessor in predecessors)
            {
                if (predecessor.Last == predecessor.First)
                {
                    if (StateMachineUtilities.IsUnconditionalBranch(predecessor.Last))
                    {
                        toBeRemoved.Add(predecessor);
                        if (!MarkTrueReturningPredecessorsAsYieldReturn(predecessor))
                        {
                            return(false);
                        }
                        continue;
                    }
                    else
                    {
                        return(false);
                    }
                }

                VariableReference flagVarReference = null;

                Instruction lastInstruction = predecessor.Last;
                if (StateMachineUtilities.IsUnconditionalBranch(lastInstruction))
                {
                    lastInstruction = lastInstruction.Previous;
                }

                int returnValue;
                if (TryGetVariableFromInstruction(lastInstruction, out flagVarReference) && CheckAndSaveReturnFlagVariable(flagVarReference) &&
                    StateMachineUtilities.TryGetOperandOfLdc(lastInstruction.Previous, out returnValue))
                {
                    if (returnValue == 1)
                    {
                        if (!TryAddToYieldReturningBlocks(predecessor))
                        {
                            return(false);
                        }
                    }
                    else if (returnValue != 0)
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Process the specified block, which ends with ret instruction.
        /// </summary>
        /// <remarks>
        /// The block should end with: return true, return false or return flagVariable.
        /// If the block ends with "return flagVariable", then we mark the block as yield break and we search for all of the predecessors of
        /// the block that set the flagVariable to true to mark them as yield returns.
        /// </remarks>
        /// <param name="theBlock"></param>
        private bool TryProcessEndBlock(InstructionBlock theBlock)
        {
            VariableReference flagVarReference = null;

            Instruction beforeRet = theBlock.Last.Previous;
            int         returnValue;

            if (StateMachineUtilities.TryGetOperandOfLdc(beforeRet, out returnValue))
            {
                if (returnValue == 0) // == return false;
                {
                    yieldBreaks.Add(theBlock);
                }
                else if (returnValue == 1) // == return true;
                {
                    int stateNumber;
                    switch (TryGetNextStateNumber(theBlock, out stateNumber))
                    {
                    case NextStateNumberSearchResult.StateNumberFound:
                        yieldReturns.Add(theBlock);

                        InstructionBlock nextState = GetStateFistBlock(stateNumber);
                        theBlock.Successors = new InstructionBlock[] { nextState };
                        break;

                    case NextStateNumberSearchResult.StateWasNotSet:
                        //If we cannot find the next state number, we assume that this is a common exit for a bunch of yield return blocks.
                        //That's why we mark all the predecessors of this block as yield returns.
                        return(MarkPredecessorsAsYieldReturns(theBlock));

                    case NextStateNumberSearchResult.PatternFailed:
                        return(false);
                    }
                }
                else
                {
                    //throw new Exception("Illegal return value of MoveNext method.");
                    return(false);
                }
            }
            else if (TryGetVariableFromInstruction(beforeRet, out flagVarReference) && CheckAndSaveReturnFlagVariable(flagVarReference))
            {
                yieldBreaks.Add(theBlock);
                return(MarkTrueReturningPredecessorsAsYieldReturn(theBlock));
            }
            else
            {
                //throw new Exception("Illegal end block of yield iterator.");
                return(false);
            }

            return(true);
        }
Exemplo n.º 7
0
        private bool TryProcessEndBlock(InstructionBlock theBlock)
        {
            V_0 = null;
            V_1 = theBlock.get_Last().get_Previous();
            if (!StateMachineUtilities.TryGetOperandOfLdc(V_1, out V_2))
            {
                if (!this.TryGetVariableFromInstruction(V_1, out V_0) || !this.CheckAndSaveReturnFlagVariable(V_0))
                {
                    return(false);
                }
                dummyVar2 = this.yieldBreaks.Add(theBlock);
                return(this.MarkTrueReturningPredecessorsAsYieldReturn(theBlock));
            }
            if (V_2 != 0)
            {
                if (V_2 != 1)
                {
                    return(false);
                }
                switch (this.TryGetNextStateNumber(theBlock, out V_3))
                {
                case 0:
                {
                    return(false);
                }

                case 1:
                {
                    dummyVar1          = this.yieldReturns.Add(theBlock);
                    V_4                = this.GetStateFistBlock(V_3);
                    stackVariable41    = new InstructionBlock[1];
                    stackVariable41[0] = V_4;
                    theBlock.set_Successors(stackVariable41);
                    break;
                }

                case 2:
                {
                    return(this.MarkPredecessorsAsYieldReturns(theBlock));
                }
                }
            }
            else
            {
                dummyVar0 = this.yieldBreaks.Add(theBlock);
            }
            return(true);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Process each CFG block to determine which cases lead to try/finally construct.
        /// </summary>
        private void DetermineExceptionHandlingStatesFromCFGBlocks()
        {
            foreach (InstructionBlock block in theDisposeCFG.Blocks)
            {
                int state;
                if ((!IsBeqInstruction(block.Last) && !IsBneUnInstruction(block.Last)) ||
                    !StateMachineUtilities.TryGetOperandOfLdc(block.Last.Previous, out state))
                {
                    continue;
                }

                Instruction branchTargetInstruction = null;
                if (IsBeqInstruction(block.Last))
                {
                    branchTargetInstruction = block.Last.Operand as Instruction;
                }
                else // bne.un*
                {
                    branchTargetInstruction = block.Last.Next as Instruction;
                }

                if (branchTargetInstruction == null)
                {
                    throw new Exception("branchTargetInstruction cannot be null.");
                }

                InstructionBlock targetBlock = SkipSingleNopInstructionBlock(theDisposeCFG.InstructionToBlockMapping[branchTargetInstruction.Offset]);
                ExceptionHandler theHandler;
                if (!TryGetExceptionHandler(targetBlock, out theHandler))
                {
                    continue;
                }

                //We've found an exception handler.

                if (!this.handlerToStatesMap.ContainsKey(theHandler))
                {
                    this.handlerToStatesMap.Add(theHandler, new HashSet <int>());
                }

                this.handlerToStatesMap[theHandler].Add(state);
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Process each switch block to determine which cases lead to try/finally constructs.
        /// </summary>
        /// <param name="switchBlockInfo"></param>
        private bool DetermineExceptionHandlingStatesFromSwitchData(SwitchData switchBlockInfo)
        {
            //Since the first try/finally that this switch covers can start at state 20, the complier will optimize this by subtracting 20 from the value of
            //the state field.
            int         stateOffset        = 0;
            Instruction currentInstruction = switchBlockInfo.SwitchBlock.Last.Previous;

            if (currentInstruction.OpCode.Code == Code.Sub)
            {
                currentInstruction = currentInstruction.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateOffset))
                {
                    return(false);
                }

                currentInstruction = currentInstruction.Previous;
            }

            InstructionBlock[] orderedCases = switchBlockInfo.OrderedCasesArray;
            for (int i = 0; i < orderedCases.Length; i++)
            {
                InstructionBlock currentCase = GetActualCase(orderedCases[i]);

                ExceptionHandler theHandler;
                if (!TryGetExceptionHandler(currentCase, out theHandler))
                {
                    continue;
                }

                //We've found an exception handler.

                if (!this.handlerToStatesMap.ContainsKey(theHandler))
                {
                    this.handlerToStatesMap.Add(theHandler, new HashSet <int>());
                }

                this.handlerToStatesMap[theHandler].Add(i + stateOffset);
            }

            return(true);
        }
        /// <summary>
        /// Checks whether the specified block is a controller block generated by the compiler in debug mode.
        /// </summary>
        /// <remarks>
        /// Pattern:
        ///
        /// ldfld stateField
        /// ldc.i4.* stateNumber
        /// ceq
        /// ldc.i4.0
        /// .....
        /// brtrue* .....
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <param name="stateNumber"></param>
        /// <returns></returns>
        private bool IsDebugControllerBlock(InstructionBlock theBlock, out int stateNumber)
        {
            if (theBlock.First == theBlock.Last)
            {
                stateNumber = -1;
                return(false);
            }

            Instruction currentInstruction = theBlock.First.Next;

            if (currentInstruction == theBlock.Last || currentInstruction.OpCode.Code != Code.Ldfld ||
                ((FieldReference)currentInstruction.Operand).Resolve() != this.stateField)
            {
                stateNumber = -1;
                return(false);
            }

            currentInstruction = currentInstruction.Next;
            if (currentInstruction == theBlock.Last || !StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
            {
                stateNumber = -1;
                return(false);
            }

            currentInstruction = currentInstruction.Next;
            if (currentInstruction == theBlock.Last || currentInstruction.OpCode.Code != Code.Ceq)
            {
                return(false);
            }

            currentInstruction = currentInstruction.Next;
            if (currentInstruction == theBlock.Last || currentInstruction.OpCode.Code != Code.Ldc_I4_0)
            {
                return(false);
            }

            return(theBlock.Last.OpCode.Code == Code.Brtrue || theBlock.Last.OpCode.Code == Code.Brtrue_S);
        }
 private bool IsDebugControllerBlock(InstructionBlock theBlock, out int stateNumber)
 {
     if ((object)theBlock.get_First() == (object)theBlock.get_Last())
     {
         stateNumber = -1;
         return(false);
     }
     V_0 = theBlock.get_First().get_Next();
     if ((object)V_0 == (object)theBlock.get_Last() || V_0.get_OpCode().get_Code() != 120 || (object)((FieldReference)V_0.get_Operand()).Resolve() != (object)this.stateField)
     {
         stateNumber = -1;
         return(false);
     }
     V_0 = V_0.get_Next();
     if ((object)V_0 == (object)theBlock.get_Last() || !StateMachineUtilities.TryGetOperandOfLdc(V_0, out stateNumber))
     {
         stateNumber = -1;
         return(false);
     }
     V_0 = V_0.get_Next();
     if ((object)V_0 == (object)theBlock.get_Last() || V_0.get_OpCode().get_Code() != 192)
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     if ((object)V_0 == (object)theBlock.get_Last() || V_0.get_OpCode().get_Code() != 22)
     {
         return(false);
     }
     if (theBlock.get_Last().get_OpCode().get_Code() == 57)
     {
         return(true);
     }
     V_1 = theBlock.get_Last().get_OpCode();
     return(V_1.get_Code() == 44);
 }
Exemplo n.º 12
0
 private YieldStateMachineControlFlowRebuilder.NextStateNumberSearchResult TryGetNextStateNumber(InstructionBlock theBlock, out int newStateNumber)
 {
     V_0 = theBlock.get_Last();
     while ((object)V_0 != (object)theBlock.get_First())
     {
         if (V_0.get_OpCode().get_Code() == 122 && (object)this.stateField == (object)((FieldReference)V_0.get_Operand()).Resolve())
         {
             V_0 = V_0.get_Previous();
             if (!StateMachineUtilities.TryGetOperandOfLdc(V_0, out newStateNumber))
             {
                 return(0);
             }
             V_0 = V_0.get_Previous().get_Previous();
             if (V_0.get_OpCode().get_Code() == 122 && this.CheckAndSaveCurrentItemField((FieldReference)V_0.get_Operand()))
             {
                 return(1);
             }
             return(0);
         }
         V_0 = V_0.get_Previous();
     }
     newStateNumber = 0;
     return(2);
 }
Exemplo n.º 13
0
 private bool TryGetDisposableConditionData(ExceptionHandler handler, out int nextState, out FieldReference enumeratorField, out FieldReference disposableField)
 {
     nextState       = -1;
     enumeratorField = null;
     disposableField = null;
     V_0             = handler.get_HandlerStart();
     V_0             = V_0.get_Next();
     if (V_0 == null || !StateMachineUtilities.TryGetOperandOfLdc(V_0, out nextState))
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 122 || (object)((FieldReference)V_0.get_Operand()).Resolve() != (object)this.stateField)
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 120)
     {
         V_0 = V_0.get_Next();
         if (V_0.get_OpCode().get_Code() != 120)
         {
             return(false);
         }
     }
     else
     {
         if (V_0.get_Next().get_OpCode().get_Code() != 43)
         {
             return(false);
         }
     }
     enumeratorField = (FieldReference)V_0.get_Operand();
     if (V_0.get_Next().get_OpCode().get_Code() != 43)
     {
         V_0 = V_0.get_Next();
         if (V_0.get_OpCode().get_Code() != 116 || String.op_Inequality(((TypeReference)V_0.get_Operand()).get_Name(), "IDisposable"))
         {
             return(false);
         }
         V_0 = V_0.get_Next();
         if (V_0.get_OpCode().get_Code() != 122)
         {
             return(false);
         }
         disposableField = (FieldReference)V_0.get_Operand();
         V_0             = V_0.get_Next();
         if (V_0 == null)
         {
             return(false);
         }
         V_0 = V_0.get_Next();
         if (V_0 == null || V_0.get_OpCode().get_Code() != 120 || V_0.get_Operand() != disposableField)
         {
             return(false);
         }
     }
     else
     {
         disposableField = enumeratorField;
         enumeratorField = null;
     }
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 43 || ((Instruction)V_0.get_Operand()).get_OpCode().get_Code() != 186)
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 120 || V_0.get_Operand() != disposableField)
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 110 || String.op_Inequality(((MethodReference)V_0.get_Operand()).get_Name(), "Dispose"))
     {
         return(false);
     }
     if (V_0.get_Next().get_OpCode().get_Code() != 186)
     {
         return(false);
     }
     return(true);
 }
Exemplo n.º 14
0
 private void DetermineExceptionHandlingStatesFromCFGBlocks()
 {
     V_0 = this.theDisposeCFG.get_Blocks();
     V_1 = 0;
     while (V_1 < (int)V_0.Length)
     {
         V_2 = V_0[V_1];
         if (this.IsBeqInstruction(V_2.get_Last()) || this.IsBneUnInstruction(V_2.get_Last()) && StateMachineUtilities.TryGetOperandOfLdc(V_2.get_Last().get_Previous(), out V_3))
         {
             V_4 = null;
             if (!this.IsBeqInstruction(V_2.get_Last()))
             {
                 V_4 = V_2.get_Last().get_Next();
             }
             else
             {
                 V_4 = V_2.get_Last().get_Operand() as Instruction;
             }
             if (V_4 == null)
             {
                 throw new Exception("branchTargetInstruction cannot be null.");
             }
             if (this.TryGetExceptionHandler(StateMachineDisposeAnalyzer.SkipSingleNopInstructionBlock(this.theDisposeCFG.get_InstructionToBlockMapping().get_Item(V_4.get_Offset())), out V_6))
             {
                 if (!this.handlerToStatesMap.ContainsKey(V_6))
                 {
                     this.handlerToStatesMap.Add(V_6, new HashSet <int>());
                 }
                 dummyVar0 = this.handlerToStatesMap.get_Item(V_6).Add(V_3);
             }
         }
         V_1 = V_1 + 1;
     }
     return;
 }
Exemplo n.º 15
0
        /// <summary>
        /// Determines wheter the finally block contains a conditional disposal.
        /// </summary>
        /// <remarks>
        /// Matches two patterns:
        /// <code>
        /// this.stateField = nextState;
        /// (this.disposableField = this.enumeratorField as IDisposable;)   -- this might be missing
        /// if(this.disposableField != null)
        /// {
        ///     this.disposableField.Dispose();
        /// }
        /// </code>
        /// </remarks>
        /// <param name="handler"></param>
        /// <param name="nextState"></param>
        /// <param name="enumeratorField"></param>
        /// <param name="disposableField"></param>
        /// <returns></returns>
        private bool TryGetDisposableConditionData(ExceptionHandler handler, out int nextState,
                                                   out FieldReference enumeratorField, out FieldReference disposableField)
        {
            nextState       = -1;
            enumeratorField = null;
            disposableField = null;

            Instruction currentInstruction = handler.HandlerStart; //ldarg.0

            currentInstruction = currentInstruction.Next;          //ldc.i4. nextState
            if (currentInstruction == null || !StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out nextState))
            {
                return(false);
            }

            currentInstruction = currentInstruction.Next;          //stfld stateField
            if (currentInstruction.OpCode.Code != Code.Stfld || ((FieldReference)currentInstruction.Operand).Resolve() != stateField)
            {
                return(false);
            }

            currentInstruction = currentInstruction.Next;          //ldarg.0
            currentInstruction = currentInstruction.Next;          //ldarg.0 ?

            if (currentInstruction.OpCode.Code == Code.Ldfld)
            {
                if (currentInstruction.Next.OpCode.Code != Code.Brfalse_S)
                {
                    return(false);
                }
            }
            else
            {
                currentInstruction = currentInstruction.Next;     //ldfld enumeratorField
                if (currentInstruction.OpCode.Code != Code.Ldfld)
                {
                    return(false);
                }
            }
            enumeratorField = (FieldReference)currentInstruction.Operand;

            if (currentInstruction.Next.OpCode.Code == Code.Brfalse_S)
            {
                disposableField = enumeratorField;
                enumeratorField = null;
            }
            else
            {
                currentInstruction = currentInstruction.Next;          //isinst [mscorlib]System.IDisposable
                if (currentInstruction.OpCode.Code != Code.Isinst || ((TypeReference)currentInstruction.Operand).Name != "IDisposable")
                {
                    return(false);
                }

                currentInstruction = currentInstruction.Next;          //stfld disposableField
                if (currentInstruction.OpCode.Code != Code.Stfld)
                {
                    return(false);
                }
                disposableField = (FieldReference)currentInstruction.Operand;

                currentInstruction = currentInstruction.Next;          //ldarg.0
                if (currentInstruction == null)
                {
                    return(false);
                }

                currentInstruction = currentInstruction.Next;          //ldfld disposableField
                if (currentInstruction == null || currentInstruction.OpCode.Code != Code.Ldfld || currentInstruction.Operand != disposableField)
                {
                    return(false);
                }
            }

            currentInstruction = currentInstruction.Next;          //brfalse.s to endfinally
            if (currentInstruction.OpCode.Code != Code.Brfalse_S || ((Instruction)currentInstruction.Operand).OpCode.Code != Code.Endfinally)
            {
                return(false);
            }

            currentInstruction = currentInstruction.Next;          //ldarg.0
            currentInstruction = currentInstruction.Next;          //ldfld disposableField
            if (currentInstruction.OpCode.Code != Code.Ldfld || currentInstruction.Operand != disposableField)
            {
                return(false);
            }

            currentInstruction = currentInstruction.Next;          //callvirt Dispose()
            if (currentInstruction.OpCode.Code != Code.Callvirt || ((MethodReference)currentInstruction.Operand).Name != "Dispose")
            {
                return(false);
            }

            if (currentInstruction.Next.OpCode.Code != Code.Endfinally)
            {
                return(false);
            }

            return(true);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Process each switch block to determine which cases lead to try/finally constructs.
        /// </summary>
        /// <remarks>
        /// E.g.: If the cases from 3 to 5 lead to the same try/finally construct then there is a try/finally construct in the MoveNext method
        /// that covers states 3, 4 and 5.
        /// </remarks>
        /// <param name="switchBlockInfo"></param>
        private bool DetermineExceptionHandlingIntervalsFromSwitchData(SwitchData switchBlockInfo)
        {
            //Since the first try/finally that this switch covers can start at state 20, the complier will optimize this by subtracting 20 from the value of
            //the state field.
            int         stateOffset        = 0;
            Instruction currentInstruction = switchBlockInfo.SwitchBlock.Last.Previous;

            if (currentInstruction.OpCode.Code == Code.Sub)
            {
                currentInstruction = currentInstruction.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateOffset))
                {
                    return(false);
                }

                currentInstruction = currentInstruction.Previous;
            }

            //The switch instruction block usually looks like this:
            //
            //ldarg.0 <- this
            //ldfld stateField
            //stloc.0
            //ldloc.0                  <- currentInstruction
            //(ldc.i4 stateOffset)
            //(sub)
            //switch ....
            currentInstruction = currentInstruction.Previous.Previous;
            if (currentInstruction.OpCode.Code != Code.Ldfld || !(currentInstruction.Operand is FieldReference) ||
                !CheckAndSaveStateField(currentInstruction.Operand as FieldReference))
            {
                //sanity check - the state field used by the Dispose method should be the same as the field used by the MoveNext method
                return(false);
            }

            //The algorithm works with the presumption that a try/finally construct contains a consecutive sequence of states.
            InstructionBlock[] orderedCases = switchBlockInfo.OrderedCasesArray;
            InstructionBlock   currentBlock = null;
            int intervalStart = -1;
            int intervalEnd   = -1;
            ExceptionHandler exceptionHandler = null;

            for (int i = 0; i < orderedCases.Length; i++)
            {
                InstructionBlock currentCase = GetActualCase(orderedCases[i]);

                if (currentBlock != null && currentCase == currentBlock) //Current block will be null, if we still haven't found an exception handler.
                {
                    intervalEnd = i + stateOffset;
                    continue;
                }

                ExceptionHandler theHandler;
                if (!TryGetExceptionHandler(currentCase, out theHandler))
                {
                    //There are cases where a state is never reached (i.e. the state field is never assigned this state number).
                    //This can create holes in the exception handlers, but since the states are never reached we can add them to the handler.
                    //(We work with the assumption that if state 3 and state 6 are handled by the same try/finally construct and 4 and 5 are not handled by
                    //any exception handler, then 4 and 5 are unreachable. True in general, but obfuscation can break this assumption.)
                    continue;
                }

                //We've found an exception handler.

                if (currentBlock != null) //If currentBlock != null, then currentBlock != currentCase. This means that we have found a new exception
                //handler, so we must store the data for the old one.
                {
                    if (!TryCreateYieldExceptionHandler(intervalStart, intervalEnd, exceptionHandler))
                    {
                        return(false);
                    }
                }
                else //Otherwise this is the first handler found for the switch block.
                {
                    currentBlock = currentCase;
                }

                intervalStart    = i + stateOffset;
                exceptionHandler = theHandler;
            }

            return(currentBlock == null ||
                   TryCreateYieldExceptionHandler(intervalStart, intervalEnd, exceptionHandler)); //Store the data for the last found exception handler.
        }
Exemplo n.º 17
0
        private bool MarkTrueReturningPredecessorsAsYieldReturn(InstructionBlock theBlock)
        {
            V_0 = (new HashSet <InstructionBlock>(theBlock.get_Predecessors())).GetEnumerator();
            try
            {
                while (V_0.MoveNext())
                {
                    V_1 = V_0.get_Current();
                    if ((object)V_1.get_Last() != (object)V_1.get_First())
                    {
                        V_2 = null;
                        V_3 = V_1.get_Last();
                        if (StateMachineUtilities.IsUnconditionalBranch(V_3))
                        {
                            V_3 = V_3.get_Previous();
                        }
                        if (!this.IsFinallyMethodInvocationBlock(V_1))
                        {
                            if (!this.TryGetVariableFromInstruction(V_3, out V_2) || !this.CheckAndSaveReturnFlagVariable(V_2) || !StateMachineUtilities.TryGetOperandOfLdc(V_3.get_Previous(), out V_4))
                            {
                                V_5 = false;
                                goto Label1;
                            }
                            else
                            {
                                if (V_4 != 1)
                                {
                                    if (V_4 == 0)
                                    {
                                        continue;
                                    }
                                    V_5 = false;
                                    goto Label1;
                                }
                                else
                                {
                                    if (this.TryAddToYieldReturningBlocks(V_1))
                                    {
                                        continue;
                                    }
                                    V_5 = false;
                                    goto Label1;
                                }
                            }
                        }
                        else
                        {
                            if (this.MarkTrueReturningPredecessorsAsYieldReturn(V_1))
                            {
                                continue;
                            }
                            V_5 = false;
                            goto Label1;
                        }
                    }
                    else
                    {
                        if (!StateMachineUtilities.IsUnconditionalBranch(V_1.get_Last()))
                        {
                            V_5 = false;
                            goto Label1;
                        }
                        else
                        {
                            dummyVar0 = this.toBeRemoved.Add(V_1);
                            if (this.MarkTrueReturningPredecessorsAsYieldReturn(V_1))
                            {
                                continue;
                            }
                            V_5 = false;
                            goto Label1;
                        }
                    }
                }
                goto Label0;
            }
            finally
            {
                ((IDisposable)V_0).Dispose();
            }
Label1:
            return(V_5);

Label0:
            return(true);
        }
        /// <summary>
        /// Determines wheter the specified block is part of the state machine controller.
        /// </summary>
        /// <remarks>
        /// We look for this pattern:
        /// ...
        /// ldloc.* stateVariable
        /// ldc.i4.* stateNumber
        /// beq* stateEntry
        ///
        /// or
        ///
        /// ....
        /// ldloc.* stateVariable
        /// (ldc.i4.* stateNumber) - can be missing
        /// (sub)                  - can be missing
        /// switch ....
        ///
        /// or
        ///
        /// ldloc.* stateVariable
        /// ldc.i4.* stateNumber
        /// bnq* default
        /// stateEntry:
        /// .........
        ///
        /// or
        ///
        /// ldfld stateField
        /// ldc.i4.* stateNumber
        /// ceq
        /// ldc.i4.0
        /// .....
        /// brtrue* default
        /// stateEntry:
        /// ............
        ///
        /// In some cases there is no state variable. Instead the state field is loaded.
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <param name="stateNumber"></param>
        /// <returns>False if the specified block is not part of the state machine controler, true - otherwise.</returns>
        private bool IsStateMachineControllerBlock(ref InstructionBlock theBlock, out StateMachineControllerType controllerType, out int stateNumber)
        {
            theBlock = SkipBranchChain(theBlock);

            Instruction currentInstruction = theBlock.Last;

            if (theCFG.SwitchBlocksInformation.ContainsKey(theBlock))
            {
                controllerType = StateMachineControllerType.Switch;

                if (currentInstruction.Previous.OpCode.Code == Code.Sub || currentInstruction.Previous.OpCode.Code == Code.Sub_Ovf)
                {
                    currentInstruction = currentInstruction.Previous.Previous;
                    if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                    {
                        return(false);
                    }
                }
                else
                {
                    stateNumber = 0;
                }
            }
            else if (IsBeqInstruction(theBlock.Last)) //controllerType == StateMachineControllerType.Conditions
            {
                controllerType = StateMachineControllerType.Condition;

                currentInstruction = theBlock.Last.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                {
                    return(false);
                }
            }
            else if (IsBneInstruction(theBlock.Last))
            {
                controllerType = StateMachineControllerType.NegativeCondition;

                currentInstruction = theBlock.Last.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                {
                    return(false);
                }
            }
            else if (IsDebugControllerBlock(theBlock, out stateNumber))
            {
                controllerType = StateMachineControllerType.NegativeCondition;
                return(true);
            }
            else
            {
                controllerType = StateMachineControllerType.None;
                stateNumber    = 0;
                return(false);
            }

            VariableReference varReference;

            if (ContainsStateFieldLoad(theBlock) ||
                TryGetVariableFromInstruction(currentInstruction.Previous, out varReference) && varReference == stateVariable &&
                !ContainsStateVariableSet(theBlock))
            //In rare cases the state variable is used in a regular switch block. That's why we check whether there is an assignment of the variable
            //in theBlock. If so then the block is not a controller block.
            {
                return(true);
            }

            stateNumber = 0;
            return(false);
        }
 private bool IsStateMachineControllerBlock(ref InstructionBlock theBlock, out StateControllerRemover.StateMachineControllerType controllerType, out int stateNumber)
 {
     theBlock = this.SkipBranchChain(theBlock);
     V_0      = theBlock.get_Last();
     if (!this.theCFG.get_SwitchBlocksInformation().ContainsKey(theBlock))
     {
         if (!this.IsBeqInstruction(theBlock.get_Last()))
         {
             if (!this.IsBrFalseInstruction(theBlock.get_Last()))
             {
                 if (!this.IsBneInstruction(theBlock.get_Last()))
                 {
                     if (this.IsDebugControllerBlock(theBlock, out stateNumber))
                     {
                         controllerType = 3;
                         return(true);
                     }
                     controllerType = 0;
                     stateNumber    = 0;
                     return(false);
                 }
                 controllerType = 3;
                 V_0            = theBlock.get_Last().get_Previous();
                 if (!StateMachineUtilities.TryGetOperandOfLdc(V_0, out stateNumber))
                 {
                     return(false);
                 }
             }
             else
             {
                 controllerType = 2;
                 V_0            = theBlock.get_Last();
                 stateNumber    = 0;
             }
         }
         else
         {
             controllerType = 2;
             V_0            = theBlock.get_Last().get_Previous();
             if (!StateMachineUtilities.TryGetOperandOfLdc(V_0, out stateNumber))
             {
                 return(false);
             }
         }
     }
     else
     {
         controllerType = 1;
         if (V_0.get_Previous().get_OpCode().get_Code() == 88 || V_0.get_Previous().get_OpCode().get_Code() == 184)
         {
             V_0 = V_0.get_Previous().get_Previous();
             if (!StateMachineUtilities.TryGetOperandOfLdc(V_0, out stateNumber))
             {
                 return(false);
             }
         }
         else
         {
             stateNumber = 0;
         }
     }
     if (this.ContainsStateFieldLoad(theBlock) || this.TryGetVariableFromInstruction(V_0.get_Previous(), out V_1) && (object)V_1 == (object)this.stateVariable && !this.ContainsStateVariableSet(theBlock))
     {
         return(true);
     }
     stateNumber = 0;
     return(false);
 }