/// <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); }
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); }
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); }
/// <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); }
/// <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); }
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); }
/// <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); } }
/// <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); }
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); }
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); }
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; }
/// <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); }
/// <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. }
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); }