// copies recursively the next basic block of the method CFG (with a switch branch as entry branch) private void copyMethodCfgRecursively(List<BasicBlock> processedBasicBlocks, BasicBlock sourceBasicBlock, ref BasicBlock targetBasicBlock, SwitchBranchTarget copiedEntryBranch, int takenEntryBranchIdx) { // check if source basic block was already processed if (processedBasicBlocks.Contains(sourceBasicBlock)) { bool found = false; foreach (BasicBlock searchBasicBlock in this.basicBlocks) { if (searchBasicBlock.id == sourceBasicBlock.id) { // set entry branch target if (takenEntryBranchIdx == -1) { copiedEntryBranch.notTakenTarget = searchBasicBlock; } else { // fill switch taken branch list with empty elements when index is out of range while (copiedEntryBranch.takenTarget.Count() <= takenEntryBranchIdx) { copiedEntryBranch.takenTarget.Add(null); } copiedEntryBranch.takenTarget[takenEntryBranchIdx] = searchBasicBlock; } searchBasicBlock.entryBranches.Add(copiedEntryBranch); found = true; break; } } if (!found) { throw new ArgumentException("Copied basic block was not found."); } return; } // add source basic block to the list of already processed basic blocks processedBasicBlocks.Add(sourceBasicBlock); // create copy of the source basic block targetBasicBlock = new BasicBlock(); this.basicBlocks.Add(targetBasicBlock); // set entry branch target if (takenEntryBranchIdx == -1) { copiedEntryBranch.notTakenTarget = targetBasicBlock; } else { // fill switch taken branch list with empty elements when index is out of range while (copiedEntryBranch.takenTarget.Count() <= takenEntryBranchIdx) { copiedEntryBranch.takenTarget.Add(null); } copiedEntryBranch.takenTarget[takenEntryBranchIdx] = targetBasicBlock; } targetBasicBlock.entryBranches.Add(copiedEntryBranch); // copy simple values targetBasicBlock.id = sourceBasicBlock.id; targetBasicBlock.semanticId = sourceBasicBlock.semanticId; targetBasicBlock.startIdx = sourceBasicBlock.startIdx; targetBasicBlock.endIdx = sourceBasicBlock.endIdx; // copy all operations of the basic block foreach (IOperation operation in sourceBasicBlock.operations) { InternalOperation copiedOperation = new InternalOperation(); copiedOperation.OperationCode = operation.OperationCode; copiedOperation.Value = operation.Value; copiedOperation.Offset = operation.Offset; copiedOperation.Location = operation.Location; targetBasicBlock.operations.Add(copiedOperation); } // process rest of the cfg and copy the exit branch if ((sourceBasicBlock.exitBranch as NoBranchTarget) != null) { NoBranchTarget exitBranch = (sourceBasicBlock.exitBranch as NoBranchTarget); // create a copied exit branch NoBranchTarget copiedExitBranch = new NoBranchTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch); } else if (sourceBasicBlock.exitBranch as UnconditionalBranchTarget != null) { UnconditionalBranchTarget exitBranch = (sourceBasicBlock.exitBranch as UnconditionalBranchTarget); // create a copied exit branch UnconditionalBranchTarget copiedExitBranch = new UnconditionalBranchTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch); } else if (sourceBasicBlock.exitBranch as ConditionalBranchTarget != null) { ConditionalBranchTarget exitBranch = (sourceBasicBlock.exitBranch as ConditionalBranchTarget); // create a copied exit branch ConditionalBranchTarget copiedExitBranch = new ConditionalBranchTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch, true); // process branch and next basic block nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.notTakenTarget, ref nextCopiedBasicBlock, copiedExitBranch, false); } else if (sourceBasicBlock.exitBranch as SwitchBranchTarget != null) { SwitchBranchTarget exitBranch = (sourceBasicBlock.exitBranch as SwitchBranchTarget); // create a copied exit branch SwitchBranchTarget copiedExitBranch = new SwitchBranchTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; // first process not taken branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.notTakenTarget, ref nextCopiedBasicBlock, copiedExitBranch, -1); // process all taken branches and next basic blocks for (int idx = 0; idx < exitBranch.takenTarget.Count(); idx++) { nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget.ElementAt(idx), ref nextCopiedBasicBlock, copiedExitBranch, idx); } } else if (sourceBasicBlock.exitBranch as ExitBranchTarget != null) { // create a copied exit branch ExitBranchTarget copiedExitBranch = new ExitBranchTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; } else if (sourceBasicBlock.exitBranch as ThrowBranchTarget != null) { // create a copied exit branch ThrowBranchTarget copiedExitBranch = new ThrowBranchTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; } else if (sourceBasicBlock.exitBranch as TryBlockTarget != null) { TryBlockTarget exitBranch = (sourceBasicBlock.exitBranch as TryBlockTarget); // create a copied exit branch TryBlockTarget copiedExitBranch = new TryBlockTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch); } else if (sourceBasicBlock.exitBranch as ExceptionBranchTarget != null) { ExceptionBranchTarget exitBranch = (sourceBasicBlock.exitBranch as ExceptionBranchTarget); // create a copied exit branch ExceptionBranchTarget copiedExitBranch = new ExceptionBranchTarget(); copiedExitBranch.sourceBasicBlock = targetBasicBlock; targetBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.exceptionTarget, ref nextCopiedBasicBlock, copiedExitBranch, true); // process branch and next basic block nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.exitTarget, ref nextCopiedBasicBlock, copiedExitBranch, false); } else { throw new ArgumentException("Do not know how to handle exit branch."); } // copy all try blocks foreach (TryBlock sourceTryBlock in sourceBasicBlock.tryBlocks) { TryBlock copiedTryBlock = new TryBlock(); copiedTryBlock.exceptionHandler = sourceTryBlock.exceptionHandler; copiedTryBlock.firstBasicBlockOfTryBlock = sourceTryBlock.firstBasicBlockOfTryBlock; copiedTryBlock.lastBasicBlockOfTryBlock = sourceTryBlock.lastBasicBlockOfTryBlock; targetBasicBlock.tryBlocks.Add(copiedTryBlock); } // copy all handler blocks foreach (HandlerBlock sourceHandlerBlock in sourceBasicBlock.handlerBlocks) { HandlerBlock copiedHandlerBlock = new HandlerBlock(); copiedHandlerBlock.exceptionHandler = sourceHandlerBlock.exceptionHandler; copiedHandlerBlock.typeOfHandler = sourceHandlerBlock.typeOfHandler; copiedHandlerBlock.firstBasicBlockOfHandlerBlock = sourceHandlerBlock.firstBasicBlockOfHandlerBlock; copiedHandlerBlock.lastBasicBlockOfHandlerBlock = sourceHandlerBlock.lastBasicBlockOfHandlerBlock; targetBasicBlock.handlerBlocks.Add(copiedHandlerBlock); } }
// builds a CFG for the given method and returns it public MethodCfg buildCfgForMethod(MethodDefinition method) { MethodCfg methodCfg = new MethodCfg(); methodCfg.method = method; // start building the cfg BasicBlock firstBasicBlock = new BasicBlock(this.semanticId); this.semanticId++; methodCfg.startBasicBlock = firstBasicBlock; this.buildRecursivelyCfg(methodCfg, method.Body.Operations, 0, null, ref firstBasicBlock); // add exception handler to the cfg foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) { // debugging variables to throw an exception if start/end of try/handler block was not found bool tryStartFound = false; bool tryEndFound = false; bool handlerStartFound = false; bool handlerEndFound = false; // search each basic block if they reside in an exception handler List<BasicBlock> localCopy = new List<BasicBlock>(); localCopy.AddRange(methodCfg.basicBlocks); for (int bbIdx = 0; bbIdx < localCopy.Count(); bbIdx++) { BasicBlock basicBlock = localCopy.ElementAt(bbIdx); int lastOperationIdx = basicBlock.operations.Count() - 1; // ignore basic block if the start of the try block lies behind the current basic block // (catch or finally blocks can never lie before a try block) if (basicBlock.operations.ElementAt(lastOperationIdx).Offset < exceptionHandler.TryStartOffset) { continue; } // check if the current basic block resides in the try block of the exception handler else if ((exceptionHandler.TryStartOffset >= basicBlock.operations.ElementAt(0).Offset && exceptionHandler.TryStartOffset <= basicBlock.operations.ElementAt(lastOperationIdx).Offset) || (exceptionHandler.TryStartOffset <= basicBlock.operations.ElementAt(0).Offset && basicBlock.operations.ElementAt(lastOperationIdx).Offset < exceptionHandler.TryEndOffset)) { TryBlock tempTryBlock = new TryBlock(); tempTryBlock.exceptionHandler = exceptionHandler; // check if the try block starts inside this basic block if (exceptionHandler.TryStartOffset >= basicBlock.operations.ElementAt(0).Offset) { // find the index of the operation that starts the try block bool foundIdx = false; for (int idx = 0; idx < basicBlock.operations.Count(); idx++) { if (basicBlock.operations.ElementAt(idx).Offset == exceptionHandler.TryStartOffset) { // if the try block does not start at the beginning of the current basic block // => split basic block and let the try block begin at the second half of the basic block if (idx != 0) { // create new basic block which will be the second half of the found one BasicBlock newBasicBlock = new BasicBlock(this.semanticId); this.semanticId++; newBasicBlock.startIdx = basicBlock.startIdx + idx; newBasicBlock.endIdx = basicBlock.endIdx; basicBlock.endIdx = basicBlock.startIdx + idx - 1; // move the exit basic blocks to the new created basic block // and make the new created basic block the exit of the splitted one newBasicBlock.exitBranch = basicBlock.exitBranch; newBasicBlock.exitBranch.sourceBasicBlock = newBasicBlock; TryBlockTarget tempExitBranch = new TryBlockTarget(); tempExitBranch.takenTarget = newBasicBlock; tempExitBranch.sourceBasicBlock = basicBlock; basicBlock.exitBranch = tempExitBranch; // add splitted basic block branch to the entry of the new one newBasicBlock.entryBranches.Add(tempExitBranch); // distribute the instructions to the basic blocks List<IOperation> previousOperations = new List<IOperation>(); List<IOperation> nextOperations = new List<IOperation>(); for (int operationIdx = 0; (operationIdx + basicBlock.startIdx) <= newBasicBlock.endIdx; operationIdx++) { if ((operationIdx + basicBlock.startIdx) < newBasicBlock.startIdx) { previousOperations.Add(basicBlock.operations.ElementAt(operationIdx)); } else { nextOperations.Add(basicBlock.operations.ElementAt(operationIdx)); } } basicBlock.operations = previousOperations; newBasicBlock.operations = nextOperations; // add new basic block to the cfg methodCfg.basicBlocks.Add(newBasicBlock); // add try block to the new created basic block (it is the start of the try block) newBasicBlock.tryBlocks.Add(tempTryBlock); // try block can not end at the first part of the splitted basic block // (because it starts at the second one), but it can end at the // second part of the splitted basic block basicBlock = newBasicBlock; lastOperationIdx = newBasicBlock.operations.Count() - 1; } // the try block starts at the beginning of the current basic block => add the try block else { basicBlock.tryBlocks.Add(tempTryBlock); } // mark try block as the beginning of the try block tempTryBlock.firstBasicBlockOfTryBlock = true; foundIdx = true; tryStartFound = true; break; } } if (!foundIdx) { throw new ArgumentException("Did not find index of operation that starts Try block."); } } else { basicBlock.tryBlocks.Add(tempTryBlock); tempTryBlock.firstBasicBlockOfTryBlock = false; } // check if the try block ends at the end of this basic block (try blocks always end at the end of a basic block) if (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)) == exceptionHandler.TryEndOffset) { tempTryBlock.lastBasicBlockOfTryBlock = true; tryEndFound = true; } else { tempTryBlock.lastBasicBlockOfTryBlock = false; } continue; } // check if the current basic block resides in the handler block of the exception handler else if ((exceptionHandler.HandlerStartOffset >= basicBlock.operations.ElementAt(0).Offset && exceptionHandler.HandlerStartOffset <= basicBlock.operations.ElementAt(lastOperationIdx).Offset) || (exceptionHandler.HandlerStartOffset <= basicBlock.operations.ElementAt(0).Offset && basicBlock.operations.ElementAt(lastOperationIdx).Offset < exceptionHandler.HandlerEndOffset)) { // check if the handler block is a catch block if (exceptionHandler.HandlerKind == HandlerKind.Catch) { HandlerBlock tempCatchBock = new HandlerBlock(); tempCatchBock.typeOfHandler = HandlerKind.Catch; tempCatchBock.exceptionHandler = exceptionHandler; basicBlock.handlerBlocks.Add(tempCatchBock); // check if the catch block starts inside this basic block if (exceptionHandler.HandlerStartOffset >= basicBlock.operations.ElementAt(0).Offset) { // find the index of the operation that starts the catch block bool foundIdx = false; for (int idx = 0; idx < basicBlock.operations.Count(); idx++) { if (basicBlock.operations.ElementAt(idx).Offset == exceptionHandler.HandlerStartOffset) { tempCatchBock.firstBasicBlockOfHandlerBlock = true; foundIdx = true; handlerStartFound = true; break; } } if (!foundIdx) { throw new ArgumentException("Did not find index of operation that starts Catch block."); } } else { tempCatchBock.firstBasicBlockOfHandlerBlock = false; } // check if the catch block ends inside this basic block if (basicBlock.operations[0].Offset < exceptionHandler.HandlerEndOffset && exceptionHandler.HandlerEndOffset <= (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)))) { // check if the catch block ends at the last instruction of this basic block (this happens usually => optimization) if (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)) == exceptionHandler.HandlerEndOffset) { tempCatchBock.lastBasicBlockOfHandlerBlock = true; handlerEndFound = true; continue; } else { throw new ArgumentException("Did not find the operation that ends Catch block."); } } else { tempCatchBock.lastBasicBlockOfHandlerBlock = false; } continue; } // check if the handler block is a finally block else if (exceptionHandler.HandlerKind == HandlerKind.Finally) { HandlerBlock tempFinallyBock = new HandlerBlock(); tempFinallyBock.typeOfHandler = HandlerKind.Finally; tempFinallyBock.exceptionHandler = exceptionHandler; basicBlock.handlerBlocks.Add(tempFinallyBock); // check if the finally block starts inside this basic block if (exceptionHandler.HandlerStartOffset >= basicBlock.operations.ElementAt(0).Offset) { // find the index of the operation that starts the finally block bool foundIdx = false; for (int idx = 0; idx < basicBlock.operations.Count(); idx++) { if (basicBlock.operations.ElementAt(idx).Offset == exceptionHandler.HandlerStartOffset) { tempFinallyBock.firstBasicBlockOfHandlerBlock = true; foundIdx = true; handlerStartFound = true; break; } } if (!foundIdx) { throw new ArgumentException("Did not find index of operation that starts Finally block."); } } else { tempFinallyBock.firstBasicBlockOfHandlerBlock = false; } // check if the finally block ends inside this basic block if (basicBlock.operations[0].Offset < exceptionHandler.HandlerEndOffset && exceptionHandler.HandlerEndOffset <= (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)))) { // check if the finally block ends at the last instruction of this basic block if (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)) == exceptionHandler.HandlerEndOffset) { tempFinallyBock.lastBasicBlockOfHandlerBlock = true; handlerEndFound = true; continue; } else { throw new ArgumentException("Did not find the operation that ends Finally block."); } } continue; } else { throw new ArgumentException("Do not know how to handle exception handler."); } } } // check if start/end of try/handler block was found if(!tryStartFound || !tryEndFound || !handlerStartFound || !handlerEndFound) { throw new ArgumentException("Was not able to find start/end of try/handler block."); } } // TODO // DEBUG //this.logger.dumpMethodCfg(methodCfg, this.logger.sanitizeString(methodCfg.method.ToString())); return methodCfg; }
// this constructor copies the given source method cfg and all its elements // NOTE: it ignores the transformation metadata public MethodCfg(MethodCfg sourceMethodCfg) { // copy link to the method this.method = sourceMethodCfg.method; // generate a list of already processed basic blocks List<BasicBlock> processedBasicBlocks = new List<BasicBlock>(); // set start basic block of the CFG as already processed processedBasicBlocks.Add(sourceMethodCfg.startBasicBlock); // create copy of start basic block BasicBlock copiedStartBasicBlock = new BasicBlock(); this.startBasicBlock = copiedStartBasicBlock; this.basicBlocks.Add(copiedStartBasicBlock); // copy simple values copiedStartBasicBlock.id = sourceMethodCfg.startBasicBlock.id; copiedStartBasicBlock.semanticId = sourceMethodCfg.startBasicBlock.semanticId; copiedStartBasicBlock.startIdx = sourceMethodCfg.startBasicBlock.startIdx; copiedStartBasicBlock.endIdx = sourceMethodCfg.startBasicBlock.endIdx; // copy all operations of the basic block foreach (IOperation operation in sourceMethodCfg.startBasicBlock.operations) { InternalOperation copiedOperation = new InternalOperation(); copiedOperation.OperationCode = operation.OperationCode; copiedOperation.Value = operation.Value; copiedOperation.Offset = operation.Offset; copiedOperation.Location = operation.Location; copiedStartBasicBlock.operations.Add(copiedOperation); } // process rest of the cfg and copy the exit branch if ((sourceMethodCfg.startBasicBlock.exitBranch as NoBranchTarget) != null) { NoBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as NoBranchTarget); // create a copied exit branch NoBranchTarget copiedExitBranch = new NoBranchTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch); } else if (sourceMethodCfg.startBasicBlock.exitBranch as UnconditionalBranchTarget != null) { UnconditionalBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as UnconditionalBranchTarget); // create a copied exit branch UnconditionalBranchTarget copiedExitBranch = new UnconditionalBranchTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch); } else if (sourceMethodCfg.startBasicBlock.exitBranch as ConditionalBranchTarget != null) { ConditionalBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as ConditionalBranchTarget); // create a copied exit branch ConditionalBranchTarget copiedExitBranch = new ConditionalBranchTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch, true); // process branch and next basic block nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.notTakenTarget, ref nextCopiedBasicBlock, copiedExitBranch, false); } else if (sourceMethodCfg.startBasicBlock.exitBranch as SwitchBranchTarget != null) { SwitchBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as SwitchBranchTarget); // create a copied exit branch SwitchBranchTarget copiedExitBranch = new SwitchBranchTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; // first process not taken branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.notTakenTarget, ref nextCopiedBasicBlock, copiedExitBranch, -1); // process all taken branches and next basic blocks for (int idx = 0; idx < exitBranch.takenTarget.Count(); idx++) { nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget.ElementAt(idx), ref nextCopiedBasicBlock, copiedExitBranch, idx); } } else if (sourceMethodCfg.startBasicBlock.exitBranch as ExitBranchTarget != null) { // create a copied exit branch ExitBranchTarget copiedExitBranch = new ExitBranchTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; } else if (sourceMethodCfg.startBasicBlock.exitBranch as ThrowBranchTarget != null) { // create a copied exit branch ThrowBranchTarget copiedExitBranch = new ThrowBranchTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; } else if (sourceMethodCfg.startBasicBlock.exitBranch as TryBlockTarget != null) { TryBlockTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as TryBlockTarget); // create a copied exit branch TryBlockTarget copiedExitBranch = new TryBlockTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch); } else if (sourceMethodCfg.startBasicBlock.exitBranch as ExceptionBranchTarget != null) { ExceptionBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as ExceptionBranchTarget); // create a copied exit branch ExceptionBranchTarget copiedExitBranch = new ExceptionBranchTarget(); copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock; copiedStartBasicBlock.exitBranch = copiedExitBranch; // process branch and next basic block BasicBlock nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.exceptionTarget, ref nextCopiedBasicBlock, copiedExitBranch, true); // process branch and next basic block nextCopiedBasicBlock = null; this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.exitTarget, ref nextCopiedBasicBlock, copiedExitBranch, false); } else { throw new ArgumentException("Do not know how to handle exit branch."); } // copy all try blocks foreach (TryBlock sourceTryBlock in sourceMethodCfg.startBasicBlock.tryBlocks) { TryBlock copiedTryBlock = new TryBlock(); copiedTryBlock.exceptionHandler = sourceTryBlock.exceptionHandler; copiedTryBlock.firstBasicBlockOfTryBlock = sourceTryBlock.firstBasicBlockOfTryBlock; copiedTryBlock.lastBasicBlockOfTryBlock = sourceTryBlock.lastBasicBlockOfTryBlock; copiedStartBasicBlock.tryBlocks.Add(copiedTryBlock); } // copy all handler blocks foreach (HandlerBlock sourceHandlerBlock in sourceMethodCfg.startBasicBlock.handlerBlocks) { HandlerBlock copiedHandlerBlock = new HandlerBlock(); copiedHandlerBlock.exceptionHandler = sourceHandlerBlock.exceptionHandler; copiedHandlerBlock.typeOfHandler = sourceHandlerBlock.typeOfHandler; copiedHandlerBlock.firstBasicBlockOfHandlerBlock = sourceHandlerBlock.firstBasicBlockOfHandlerBlock; copiedHandlerBlock.lastBasicBlockOfHandlerBlock = sourceHandlerBlock.lastBasicBlockOfHandlerBlock; copiedStartBasicBlock.handlerBlocks.Add(copiedHandlerBlock); } }