예제 #1
0
        // creates a new CCI operation
        private static IOperation createNewOperation(OperationCode operationCode, object value = null,
                                                     ILocation location = null, uint offset = 0)
        {
            InternalOperation newOperation = new InternalOperation();

            newOperation.OperationCode = operationCode;
            newOperation.Value         = value;
            newOperation.Location      = location;
            newOperation.Offset        = offset;

            return(newOperation);
        }
예제 #2
0
        // adds a nop instruction after every instruction in the given method cfg
        public void addNopsToCfg(MethodCfg methodCfg) {

            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                List<IOperation> newOperations = new List<IOperation>();
                for (int idx = 0; idx < tempBB.operations.Count(); idx++) {

                    IOperation currentOperation = tempBB.operations.ElementAt(idx);

                    // copy current operation to new operations list
                    newOperations.Add(currentOperation);

                    if (idx == tempBB.operations.Count() - 1) {
                        break;
                    }

                    // ignore all prefixes (because nop after prefix will crash the program)
                    if (currentOperation.OperationCode == OperationCode.No_
                        || currentOperation.OperationCode == OperationCode.Constrained_
                        || currentOperation.OperationCode == OperationCode.Readonly_
                        || currentOperation.OperationCode == OperationCode.Tail_
                        || currentOperation.OperationCode == OperationCode.Unaligned_
                        || currentOperation.OperationCode == OperationCode.Volatile_) {
                        continue;
                    }

                    InternalOperation newNopOperation = new InternalOperation();
                    newNopOperation.OperationCode = OperationCode.Nop;

                    // add nop operation after current one
                    newOperations.Add(newNopOperation);

                }

                // replace old operations with new ones
                tempBB.operations = newOperations;

            }

        }
예제 #3
0
        // adds a nop instruction after every instruction in the given method cfg
        public void addNopsToCfg(MethodCfg methodCfg)
        {
            foreach (BasicBlock tempBB in methodCfg.basicBlocks)
            {
                List <IOperation> newOperations = new List <IOperation>();
                for (int idx = 0; idx < tempBB.operations.Count(); idx++)
                {
                    IOperation currentOperation = tempBB.operations.ElementAt(idx);

                    // copy current operation to new operations list
                    newOperations.Add(currentOperation);

                    if (idx == tempBB.operations.Count() - 1)
                    {
                        break;
                    }

                    // ignore all prefixes (because nop after prefix will crash the program)
                    if (currentOperation.OperationCode == OperationCode.No_ ||
                        currentOperation.OperationCode == OperationCode.Constrained_ ||
                        currentOperation.OperationCode == OperationCode.Readonly_ ||
                        currentOperation.OperationCode == OperationCode.Tail_ ||
                        currentOperation.OperationCode == OperationCode.Unaligned_ ||
                        currentOperation.OperationCode == OperationCode.Volatile_)
                    {
                        continue;
                    }

                    InternalOperation newNopOperation = new InternalOperation();
                    newNopOperation.OperationCode = OperationCode.Nop;

                    // add nop operation after current one
                    newOperations.Add(newNopOperation);
                }

                // replace old operations with new ones
                tempBB.operations = newOperations;
            }
        }
예제 #4
0
        // creates a method for a given method CFG (IMPORTANT: it updates the operations
        // and exception handlers of the existing method, does not create a new method)
        public void createMethodFromCfg(MethodCfg methodCfg) {

            // list of basic blocks that belong together logically (i.e. BB2 lies directly behind BB1 because it reaches it without a branch)
            IList<BasicBlockUnion> basicBlockUnions = new List<BasicBlockUnion>();

            // first step: create basic block unions
            // create first basic block union starting from the start basic block
            BasicBlockUnion firstBasicBlockUnion = new BasicBlockUnion();
            this.createRecursivelyBasicBlockUnion(basicBlockUnions, firstBasicBlockUnion, methodCfg.startBasicBlock);
            basicBlockUnions.Add(firstBasicBlockUnion);

            // create basic block unions for the rest of the basic blocks
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // create a basic block union (if basic block is not contained by another existing basic block union)
                BasicBlockUnion basicBlockUnion = new BasicBlockUnion();
                this.createRecursivelyBasicBlockUnion(basicBlockUnions, basicBlockUnion, tempBB);

                // if the newly created basic block union contains basic blocks
                // => add to list of basic block unions
                if (basicBlockUnion.basicBlocks.Count() != 0) {
                    basicBlockUnions.Add(basicBlockUnion);
                }
            }


            // step two: merge basic block unions with respect to the exception handler
            foreach (OperationExceptionInformation exceptionHandler in methodCfg.method.Body.OperationExceptionInformation) {

                // create a temporary object to reorder the basic block unions with respect to the exception handler
                BasicBlockUnionExceptionHandlerOrder tempNewOrder = new BasicBlockUnionExceptionHandlerOrder();
                tempNewOrder.exceptionHandler = exceptionHandler;

                // find all basic blocks that are connected to the current exception handler
                foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                    foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {

                        // ignore all basic blocks that do not have any try/catch/finally handler in it
                        if (basicBlock.tryBlocks.Count() == 0 && basicBlock.handlerBlocks.Count() == 0) {
                            continue;
                        }

                        // find the try block that is connected to the current exception handler
                        foreach (TryBlock tryBlock in basicBlock.tryBlocks) {

                            // ignore try blocks that do not belong to the current exception handler
                            if (tryBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in try body
                            // if not => add to try body
                            if (!tempNewOrder.tryBody.Contains(basicBlockUnion)) {
                                tempNewOrder.tryBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the try block
                            if (tryBlock.firstBasicBlockOfTryBlock) {
                                tempNewOrder.tryStart = basicBlockUnion;
                            }

                            // check if the basic block ends the try block
                            if (tryBlock.lastBasicBlockOfTryBlock) {
                                tempNewOrder.tryEnd = basicBlockUnion;
                            }
                        }

                        // find the handler block that is connected to the current exception handler
                        foreach (HandlerBlock handlerBlock in basicBlock.handlerBlocks) {

                            // ignore handler blocks that do not belong to the current exception handler
                            if (handlerBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in handler body
                            // if not => add to handler body
                            if (!tempNewOrder.handlerBody.Contains(basicBlockUnion)) {
                                tempNewOrder.handlerBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the handler block
                            if (handlerBlock.firstBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerStart = basicBlockUnion;
                            }

                            // check if the basic block ends the handler block
                            if (handlerBlock.lastBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerEnd = basicBlockUnion;
                            }
                        }
                    }
                }
                if (tempNewOrder.tryStart == null
                    || tempNewOrder.tryEnd == null
                    || tempNewOrder.handlerStart == null
                    || tempNewOrder.handlerEnd == null) {
                        throw new ArgumentException("Could not find all try/catch beginnings/ends.");
                }



                // merge basic block unions with respect to the current exception handler

                // check if the complete exception handling is done in only one basic block union
                // => ignore it
                if (tempNewOrder.tryStart == tempNewOrder.tryEnd
                    && tempNewOrder.handlerStart == tempNewOrder.handlerEnd
                    && tempNewOrder.tryStart == tempNewOrder.handlerStart) {
                    continue;
                }

                // if not everything lies in the same basic block union
                // extend the basic block union that starts the try block
                BasicBlockUnion extendedUnion = tempNewOrder.tryStart;

                // if try block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.tryStart != tempNewOrder.tryEnd) {
                    foreach (BasicBlockUnion tryBodyBasicBlockUnion in tempNewOrder.tryBody) {

                        // ignore the basic block union that starts the try block (already in extended union)
                        // and ignore the basic block union that ends the try block (is added last)
                        if (tryBodyBasicBlockUnion == tempNewOrder.tryStart
                            || tryBodyBasicBlockUnion == tempNewOrder.tryEnd) {
                            continue;
                        }

                        // extend first basic block union with the basic block union of the
                        // try block body and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(tryBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(tryBodyBasicBlockUnion);
                    }

                    // extend first basic block union with the basic block union of the
                    // try block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.tryEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.tryEnd);
                }

                // if the try block end and the handler block start are not the same basic block union
                // => merge the union of the handler block start to the current basic block union
                if (tempNewOrder.tryEnd != tempNewOrder.handlerStart) {
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerStart.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerStart);
                }

                // if handler block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.handlerStart != tempNewOrder.handlerEnd) {
                    foreach (BasicBlockUnion handlerBodyBasicBlockUnion in tempNewOrder.handlerBody) {

                        // ignore the basic block union that starts the handler block (already in extended union)
                        // and ignore the basic block union that ends the handler block (is added last)
                        if (handlerBodyBasicBlockUnion == tempNewOrder.handlerStart
                            || handlerBodyBasicBlockUnion == tempNewOrder.handlerEnd) {
                            continue;
                        }

                        // add basic block union of the handler block body to the extended basic block union 
                        // and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(handlerBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(handlerBodyBasicBlockUnion);
                    }

                    // extend the extended basic block union with the basic block union of the
                    // handler block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerEnd);
                }
            }


            // step three: create one list of operations and modify jump offsets
            // create a list of operations from the basic blocks,
            // update basic block start/end indices accordingly
            // and update the offsets of the operations (needed to update branch operations)
            IList<IOperation> methodOperations = new List<IOperation>();
            int operationIdx = 0;
            uint currentOffset = 0;
            foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {
                    basicBlock.startIdx = operationIdx;
                    //foreach (IOperation operation in basicBlock.operations) {
                    for (int opIdx = 0; opIdx < basicBlock.operations.Count(); opIdx++) {
                        IOperation operation = basicBlock.operations.ElementAt(opIdx);

                        // a new operation object is needed because the old operations
                        // are read only due to cci
                        InternalOperation newOperation = new InternalOperation();

                        // exchange every short instruction with its larger one
                        switch (operation.OperationCode) {
                            case OperationCode.Beq_S:
                                newOperation.OperationCode = OperationCode.Beq;
                                break;
                            case OperationCode.Bge_S:
                                newOperation.OperationCode = OperationCode.Bge;
                                break;
                            case OperationCode.Bge_Un_S:
                                newOperation.OperationCode = OperationCode.Bge_Un;
                                break;
                            case OperationCode.Bgt_S:
                                newOperation.OperationCode = OperationCode.Bgt;
                                break;
                            case OperationCode.Bgt_Un_S:
                                newOperation.OperationCode = OperationCode.Bgt_Un;
                                break;
                            case OperationCode.Ble_S:
                                newOperation.OperationCode = OperationCode.Ble;
                                break;
                            case OperationCode.Ble_Un_S:
                                newOperation.OperationCode = OperationCode.Ble_Un;
                                break;
                            case OperationCode.Blt_S:
                                newOperation.OperationCode = OperationCode.Blt;
                                break;
                            case OperationCode.Blt_Un_S:
                                newOperation.OperationCode = OperationCode.Blt_Un;
                                break;
                            case OperationCode.Bne_Un_S:
                                newOperation.OperationCode = OperationCode.Bne_Un;
                                break;
                            case OperationCode.Br_S:
                                newOperation.OperationCode = OperationCode.Br;
                                break;
                            case OperationCode.Brfalse_S:
                                newOperation.OperationCode = OperationCode.Brfalse;
                                break;
                            case OperationCode.Brtrue_S:
                                newOperation.OperationCode = OperationCode.Brtrue;
                                break;
                            case OperationCode.Ldarg_S:
                                newOperation.OperationCode = OperationCode.Ldarg;
                                break;
                            case OperationCode.Ldarga_S:
                                newOperation.OperationCode = OperationCode.Ldarga;
                                break;
                            case OperationCode.Ldc_I4_S:
                                newOperation.OperationCode = OperationCode.Ldc_I4;
                                break;
                            case OperationCode.Ldloc_S:
                                newOperation.OperationCode = OperationCode.Ldloc;
                                break;
                            case OperationCode.Ldloca_S:
                                newOperation.OperationCode = OperationCode.Ldloca;
                                break;
                            case OperationCode.Leave_S:
                                newOperation.OperationCode = OperationCode.Leave;
                                break;
                            case OperationCode.Starg_S:
                                newOperation.OperationCode = OperationCode.Starg;
                                break;
                            case OperationCode.Stloc_S:
                                newOperation.OperationCode = OperationCode.Stloc;
                                break;
                            default:
                                newOperation.OperationCode = operation.OperationCode;
                                break;
                        }
                        newOperation.Value = operation.Value;
                        newOperation.Location = operation.Location;
                        newOperation.Offset = currentOffset;
                        methodOperations.Add(newOperation);

                        // replace old operation in basic block with newly created one
                        basicBlock.operations[opIdx] = newOperation;

                        operationIdx++;
                        currentOffset += CfgBuilder.getSizeOfOperation(newOperation);
                    }
                    basicBlock.endIdx = operationIdx - 1;
                }
            }


            // step four: update branches with new target offsets
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {
                InternalOperation branchOperation = (InternalOperation)methodOperations.ElementAt(tempBB.endIdx);

                // check which kind of exit branch is used by this basic block and update its operation accordingly
                if (tempBB.exitBranch as NoBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as TryBlockTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ConditionalBranchTarget != null) {
                    ConditionalBranchTarget tempExitBranch = (tempBB.exitBranch as ConditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as SwitchBranchTarget != null) {
                    SwitchBranchTarget tempExitBranch = (tempBB.exitBranch as SwitchBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // update all switch branches
                    for (int switchIdx = 0; switchIdx < tempExitBranch.takenTarget.Count(); switchIdx++) {

                        // get index of the branch target
                        int targetBranchIdx = tempExitBranch.takenTarget.ElementAt(switchIdx).startIdx;

                        // update offset of the taken branch
                        ((uint[])branchOperation.Value)[switchIdx] = methodOperations.ElementAt(targetBranchIdx).Offset;
                    }
                }
                else if (tempBB.exitBranch as UnconditionalBranchTarget != null) {
                    UnconditionalBranchTarget tempExitBranch = (tempBB.exitBranch as UnconditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as ExitBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ThrowBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ExceptionBranchTarget != null) {
                    ExceptionBranchTarget tempExitBranch = (tempBB.exitBranch as ExceptionBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.exitTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else {
                    throw new ArgumentException("Do not know how to handle exit branch.");
                }
            }


            // step five: create new exception handler with updated offsets and
            // create new method body of the cci method
            MethodDefinition method = methodCfg.method;
            var ilGenerator = new ILGenerator(this.host, method);
            // emit all operations to the new body
            foreach (IOperation operation in methodOperations) {
                ilGenerator.Emit(operation.OperationCode, operation.Value);
            }

            // list that is used to replace the pointer to the old exception handler in the basic blocks to the new exception handler
            List<OldExceptionHandlerMapping> oldExceptionHandlerMappings = new List<OldExceptionHandlerMapping>();
            
            // create for each old exception handler a new one with updated data
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // create mapping object for old exception handler
                OldExceptionHandlerMapping oldExceptionHandlerMapping = new OldExceptionHandlerMapping();
                oldExceptionHandlerMapping.oldExceptionHandler = exceptionHandler;
                oldExceptionHandlerMappings.Add(oldExceptionHandlerMapping);

                ILGeneratorLabel tryStart = new ILGeneratorLabel();
                ILGeneratorLabel tryEnd = new ILGeneratorLabel();
                ILGeneratorLabel handlerStart = new ILGeneratorLabel();
                ILGeneratorLabel handlerEnd = new ILGeneratorLabel();
                ILGeneratorLabel filterStart = new ILGeneratorLabel();

                // search for the basic blocks that start/end the try block and handler block
                foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                    foreach (TryBlock tempTryBlock in tempBB.tryBlocks) {

                        // ignore try blocks that do not belong to the current exception handler
                        if (tempTryBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset of the instruction that starts the try block
                        if (tempTryBlock.firstBasicBlockOfTryBlock) {
                            tryStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.tryStartOffset = tryStart.Offset;
                        }

                        // get offset of the instruction that ends the try block (always the last instruction of the basic block)
                        if (tempTryBlock.lastBasicBlockOfTryBlock) {
                            tryEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            tryEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.tryEndOffset = tryEnd.Offset;
                        }
                    }

                    foreach (HandlerBlock tempHandlerBlock in tempBB.handlerBlocks) {

                        // ignore handler blocks that do not belong to the current exception handler
                        if (tempHandlerBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset ot the instruction that starts the handler block
                        if (tempHandlerBlock.firstBasicBlockOfHandlerBlock) {
                            handlerStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.handlerStartOffset = handlerStart.Offset;
                        }

                        // get offset of the instruction that ends the handler block
                        if (tempHandlerBlock.lastBasicBlockOfHandlerBlock) {
                            handlerEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            handlerEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.handlerEndOffset = handlerEnd.Offset;
                        }
                    }
                }

                // copy the exception handler filter
                filterStart.Offset = exceptionHandler.FilterDecisionStartOffset;
                oldExceptionHandlerMapping.filterStartOffset = filterStart.Offset;

                // add new exception handler
                oldExceptionHandlerMapping.exceptionType = exceptionHandler.ExceptionType;
                oldExceptionHandlerMapping.handlerKind = exceptionHandler.HandlerKind;
                ilGenerator.AddExceptionHandlerInformation(exceptionHandler.HandlerKind, exceptionHandler.ExceptionType, tryStart, tryEnd, handlerStart, handlerEnd, filterStart);
            }

            // create the body
            List<ILocalDefinition> variableListCopy = new List<ILocalDefinition>(method.Body.LocalVariables);
            List<ITypeDefinition> privateHelperTypesListCopy = new List<ITypeDefinition>(method.Body.PrivateHelperTypes);
            var newBody = new ILGeneratorMethodBody(ilGenerator, method.Body.LocalsAreZeroed, 8, method, variableListCopy, privateHelperTypesListCopy); // TODO dynamic max stack size?
            method.Body = newBody;


            // step six: replace pointer to the old exception handler with the new exception handler

            // map all old exception handler to the new objects
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // search for the new exception handler object to get the mapping to the old one
                bool found = false;
                foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                    if (oldExceptionHandlerMapping.exceptionType == exceptionHandler.ExceptionType
                        && oldExceptionHandlerMapping.handlerKind == exceptionHandler.HandlerKind
                        && oldExceptionHandlerMapping.filterStartOffset == exceptionHandler.FilterDecisionStartOffset
                        && oldExceptionHandlerMapping.tryStartOffset == exceptionHandler.TryStartOffset
                        && oldExceptionHandlerMapping.tryEndOffset == exceptionHandler.TryEndOffset
                        && oldExceptionHandlerMapping.handlerStartOffset == exceptionHandler.HandlerStartOffset
                        && oldExceptionHandlerMapping.handlerEndOffset == exceptionHandler.HandlerEndOffset) {
                        oldExceptionHandlerMapping.newExceptionHandler = exceptionHandler;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    throw new ArgumentException("Not able to map old exception handler to new one.");
                }
            }

            // replace all old exception handler in the basic blocks with the new exception handler
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // replace all exception handler in the try blocks
                foreach (TryBlock tryBlock in tempBB.tryBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (tryBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            tryBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }

                // replace all exception handler in the handler blocks
                foreach (HandlerBlock handlerBlock in tempBB.handlerBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (handlerBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            handlerBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }
            }

            
            // TODO
            // DEBUG
            /*
            // sanitize method name to store it as a file
            String invalidChars = System.Text.RegularExpressions.Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars()));
            String invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars);
            String fileName = System.Text.RegularExpressions.Regex.Replace(methodCfg.method.ToString(), invalidRegStr, "_");
            fileName = fileName.Length >= 230 ? fileName.Substring(0, 230) : fileName;

            // dump cfg created from the exit branches
            System.IO.StreamWriter dotFile = new System.IO.StreamWriter("e:\\" + "\\BBUnion_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            for (int bbuidx = 0; bbuidx < basicBlockUnions.Count(); bbuidx++) {
                BasicBlockUnion basicBlockUnion = basicBlockUnions.ElementAt(bbuidx);
                    // write all basic blocks to .dot file
                    for (int idx = 0; idx < basicBlockUnion.basicBlocks.Count(); idx++) {

                        BasicBlock currentBasicBlock = basicBlockUnion.basicBlocks.ElementAt(idx);

                        // write the current basic block to the file and all its instructions
                        dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [shape=record]");
                        bool first = true;
                        for (int opIdx = 0; opIdx < currentBasicBlock.operations.Count(); opIdx++) {
                            var operation = currentBasicBlock.operations.ElementAt(opIdx);
                            if (first) {
                                dotFile.Write("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [label=\"{");
                                first = false;
                            }
                            else {
                                dotFile.Write("|");
                            }

                            // insert try block beginnings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.firstBasicBlockOfTryBlock && opIdx == 0) {
                                    dotFile.Write("TRY START (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                }
                            }

                            // insert catch block beginnings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.firstBasicBlockOfHandlerBlock && opIdx == 0) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("CATCH START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("FINALLY START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }

                            // check if instruction has an argument
                            if (operation.Value != null) {
                                dotFile.Write(operation.OperationCode.ToString() + " " + operation.Value.ToString());
                            }
                            else {
                                dotFile.Write(operation.OperationCode.ToString());
                            }

                            // insert try block endings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.lastBasicBlockOfTryBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    dotFile.Write("|TRY END (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                }
                            }

                            // insert catch block endings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.lastBasicBlockOfHandlerBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("|CATCH END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("|FINALLY END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }
                        }
                        dotFile.WriteLine("}\"]");


                        if ((idx + 1) < basicBlockUnion.basicBlocks.Count()) {
                            dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " -> BB" + bbuidx.ToString() + "_" + (idx + 1).ToString() + "[ color=\"blue\" ]");
                        }

                    }
                }


            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();
            */
        }
예제 #5
0
        // 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);
            }

        }
예제 #6
0
        // 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);
            }

        }
예제 #7
0
        // creates a new CCI operation
        private static IOperation createNewOperation(OperationCode operationCode, object value=null,
            ILocation location=null, uint offset=0)
        {
            InternalOperation newOperation = new InternalOperation();
            newOperation.OperationCode = operationCode;
            newOperation.Value = value;
            newOperation.Location = location;
            newOperation.Offset = offset;

            return newOperation;
        }