コード例 #1
0
        // insert the given new target basic block between the given switch branch to manipulate
        public void insertBasicBlockBetweenBranch(SwitchBranchTarget branchToManipulate, int manipulateTakenBranchIdx, BasicBlock newTarget, ConditionalBranchTarget exitBranch, bool useTakenBranch) {

            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = null;

            // check wether to use the taken or not taken part of the exit branch
            if (useTakenBranch) {

                outroBasicBlock = branchToManipulate.takenTarget.ElementAt(manipulateTakenBranchIdx);
                BasicBlock tempTakenTarget = null;

                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref tempTakenTarget, newTarget, newTarget, exitBranch, ref exitBranch.takenTarget);

                branchToManipulate.takenTarget[manipulateTakenBranchIdx] = tempTakenTarget;
            }
            else {

                outroBasicBlock = branchToManipulate.takenTarget.ElementAt(manipulateTakenBranchIdx);
                BasicBlock tempTakenTarget = null;

                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref tempTakenTarget, newTarget, newTarget, exitBranch, ref exitBranch.notTakenTarget);

                branchToManipulate.takenTarget[manipulateTakenBranchIdx] = tempTakenTarget;
            }
        }
コード例 #2
0
        // insert the given new target basic block between the given conditional branch to manipulate
        public void insertBasicBlockBetweenBranch(ConditionalBranchTarget branchToManipulate, bool manipulateTakenBranch, BasicBlock newTarget, SwitchBranchTarget exitBranch, int switchTakenBranchIdx) {

            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = null;

            // check wether to manipulate the taken or not taken branch of the branch to manipulate
            if (manipulateTakenBranch) {
                outroBasicBlock = branchToManipulate.takenTarget;
                BasicBlock tempTakenTarget = null;
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref tempTakenTarget);

                // fill switch taken branch list with null when index is out of range
                while (exitBranch.takenTarget.Count() <= switchTakenBranchIdx) {
                    exitBranch.takenTarget.Add(null);
                }

                exitBranch.takenTarget[switchTakenBranchIdx] = tempTakenTarget;
            }
            else {
                BasicBlock tempTakenTarget = null;
                outroBasicBlock = branchToManipulate.notTakenTarget;
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.notTakenTarget, newTarget, newTarget, exitBranch, ref tempTakenTarget);

                // fill switch taken branch list with null when index is out of range
                while (exitBranch.takenTarget.Count() <= switchTakenBranchIdx) {
                    exitBranch.takenTarget.Add(null);
                }

                exitBranch.takenTarget[switchTakenBranchIdx] = tempTakenTarget;
            }

        }
コード例 #3
0
        // insert the given new target basic block (given by start and end block) between the given conditional branch to manipulate
        public void insertBasicBlockBetweenBranch(ConditionalBranchTarget branchToManipulate, bool manipulateTakenBranch, BasicBlock newTargetStart, BasicBlock newTargetEnd, UnconditionalBranchTarget exitBranch) {
            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = null;

            // manipulate the correct branch
            if (manipulateTakenBranch) {
                outroBasicBlock = branchToManipulate.takenTarget;
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTargetStart, newTargetEnd, exitBranch, ref exitBranch.takenTarget);
            }
            else {
                outroBasicBlock = branchToManipulate.notTakenTarget;
                this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.notTakenTarget, newTargetStart, newTargetEnd, exitBranch, ref exitBranch.takenTarget);
            }
        }
コード例 #4
0
ファイル: Cfg.cs プロジェクト: RUB-SysSec/Probfuscator
        // build recursively the cfg of the given operations
        private void buildRecursivelyCfg(MethodCfg methodCfg, IEnumerable<IOperation> operations, int currentIdx, IBranchTarget entryBranch, ref BasicBlock currentBasicBlock) {

            // check if a new basic block has to be created
            for (int bbIdx = 0; bbIdx < methodCfg.basicBlocks.Count(); bbIdx++) {

                // check if the current index points into an existing basic block
                // => split basic block
                BasicBlock tempBB = methodCfg.basicBlocks.ElementAt(bbIdx);
                if (tempBB.startIdx < currentIdx && tempBB.endIdx >= currentIdx) {

                    // create new basic block which will be the second half of the found one
                    BasicBlock newBasicBlock = new BasicBlock(this.semanticId);
                    this.semanticId++;
                    newBasicBlock.startIdx = currentIdx;
                    newBasicBlock.endIdx = tempBB.endIdx;
                    tempBB.endIdx = currentIdx - 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 = tempBB.exitBranch;
                    newBasicBlock.exitBranch.sourceBasicBlock = newBasicBlock;
                    NoBranchTarget tempExitBranch = new NoBranchTarget();
                    tempExitBranch.takenTarget = newBasicBlock;
                    tempExitBranch.sourceBasicBlock = tempBB;
                    tempBB.exitBranch = tempExitBranch;

                    // set the current basic block to the new created basic block
                    currentBasicBlock = newBasicBlock;

                    // add splitted basic block branch and basic block branch that leads to this split
                    // to the entries of the new one
                    newBasicBlock.entryBranches.Add(entryBranch);
                    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 + tempBB.startIdx) <= newBasicBlock.endIdx; operationIdx++) {

                        if ((operationIdx + tempBB.startIdx) < currentIdx) {
                            previousOperations.Add(tempBB.operations.ElementAt(operationIdx));
                        }
                        else {
                            nextOperations.Add(tempBB.operations.ElementAt(operationIdx));
                        }
                    }
                    tempBB.operations = previousOperations;
                    newBasicBlock.operations = nextOperations;

                    // add new basic block to the cfg
                    methodCfg.basicBlocks.Add(newBasicBlock);

                    return;
                }

                // if the current index of the operation points to the start index of an existing basic block
                // => update entry branches
                else if (tempBB.startIdx == currentIdx && entryBranch != null && currentBasicBlock != null) {
                    tempBB.entryBranches.Add(entryBranch);

                    // set the found basic block as the current basic block
                    currentBasicBlock = tempBB;
                    return;
                }

                // if the current index of the operation points to the start index of an existing basic block, has no entry branch
                // and is not the first instruction
                // set the current basic block to the found one
                else if (currentIdx != 0 && tempBB.startIdx == currentIdx && currentBasicBlock != null) {

                    // set the found basic block as the current basic block
                    currentBasicBlock = tempBB;
                    return;

                }

            }

            // set index of current basic block and add it to the cfg
            currentBasicBlock.startIdx = currentIdx;
            methodCfg.basicBlocks.Add(currentBasicBlock);

            // check if the basic block was jumped to from another basic block
            // => update entry branches
            if (entryBranch != null) {
                currentBasicBlock.entryBranches.Add(entryBranch);
            }

            // parse every instruction to find branches etc
            for (int idx = currentIdx; idx < operations.Count(); idx++) {

                // check if the current instruction is the start instruction of an already existing basic block (except the current basic block)
                // => add the current basic block to the list of entry basic blocks, the found basic block to the list of exit basic blocks and set the index
                for (int bbIdx = 0; bbIdx < methodCfg.basicBlocks.Count(); bbIdx++) {
                    BasicBlock tempBB = methodCfg.basicBlocks.ElementAt(bbIdx);
                    if (tempBB.startIdx == idx && tempBB != currentBasicBlock) {
                        currentBasicBlock.endIdx = idx - 1;

                        // create new exit branch and add it
                        NoBranchTarget currentExitBranch = new NoBranchTarget();
                        currentExitBranch.sourceBasicBlock = currentBasicBlock;
                        currentExitBranch.takenTarget = tempBB;
                        currentBasicBlock.exitBranch = currentExitBranch;

                        // add current exit branch as entry for the found one
                        tempBB.entryBranches.Add(currentExitBranch);
                        return;
                    }
                }

                // add current instruction to the basic block
                var operation = operations.ElementAt(idx);
                currentBasicBlock.operations.Add(operation);

                // check for special instructions like branches
                switch (operation.OperationCode) {

                    // conditional branch instructions
                    case OperationCode.Beq:
                    case OperationCode.Bge:
                    case OperationCode.Bge_Un:
                    case OperationCode.Bgt:
                    case OperationCode.Bgt_Un:
                    case OperationCode.Ble:
                    case OperationCode.Ble_Un:
                    case OperationCode.Blt:
                    case OperationCode.Blt_Un:
                    case OperationCode.Bne_Un:
                    case OperationCode.Brfalse:
                    case OperationCode.Brtrue:
                    case OperationCode.Beq_S:
                    case OperationCode.Bge_S:
                    case OperationCode.Bge_Un_S:
                    case OperationCode.Bgt_S:
                    case OperationCode.Bgt_Un_S:
                    case OperationCode.Ble_S:
                    case OperationCode.Ble_Un_S:
                    case OperationCode.Blt_S:
                    case OperationCode.Blt_Un_S:
                    case OperationCode.Bne_Un_S:
                    case OperationCode.Brfalse_S:
                    case OperationCode.Brtrue_S: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // calculate the target index of the branch
                            int branchTargetIdx = 0;
                            uint branchTargetOffset;

                            // do operation value can be of type long which can not be casted in this way
                            if (operation.Value is long) {
                                branchTargetOffset = Convert.ToUInt32(operation.Value);
                            }
                            else {
                                branchTargetOffset = (uint)operation.Value;
                            }

                            while (true) {
                                if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                    break;
                                }
                                else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                    throw new ArgumentException("Could not find target off branch.");
                                }
                                branchTargetIdx++;
                            }

                            // create new exit branch object
                            ConditionalBranchTarget currentExitBranch = new ConditionalBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.notTakenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentExitBranch.takenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start two new basic blocks from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.notTakenTarget);
                            this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref currentExitBranch.takenTarget);
                            return;
                        }

                    // unconditional branch instructions
                    case OperationCode.Br:
                    case OperationCode.Br_S: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // calculate the target index of the branch
                            int branchTargetIdx = 0;
                            uint branchTargetOffset = (uint)operation.Value;
                            while (true) {
                                if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                    break;
                                }
                                else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                    throw new ArgumentException("Could not find target off branch.");
                                }
                                branchTargetIdx++;
                            }

                            // create new exit branch object
                            UnconditionalBranchTarget currentExitBranch = new UnconditionalBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.takenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start one new basic block from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref currentExitBranch.takenTarget);
                            return;
                        }

                    // exit operation
                    case OperationCode.Ret: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            ExitBranchTarget currentExitBranch = new ExitBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // end current execution
                            return;
                        }

                    // operations that exit the current function/control flow
                    case OperationCode.Throw: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            ThrowBranchTarget currentExitBranch = new ThrowBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start a new basic block if this was not the last instruction of the method
                            // (needed because some control flows that are reached via throw are not found without it) 
                            if ((idx + 1) < operations.Count()) {
                                BasicBlock newStartBasicBlock = new BasicBlock(this.semanticId);
                                this.semanticId++;
                                this.buildRecursivelyCfg(methodCfg, operations, idx + 1, null, ref newStartBasicBlock);
                            }

                            // end current execution
                            return;
                        }

                    // switch instruction (has a variable set of jump targets)
                    case OperationCode.Switch: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            SwitchBranchTarget currentExitBranch = new SwitchBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.notTakenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // calculate the target index of all switch branches
                            int counter = 0;
                            foreach (uint branchTargetOffset in (uint[])operation.Value) {
                                int branchTargetIdx = 0;
                                while (true) {
                                    if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                        break;
                                    }
                                    else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                        throw new ArgumentException("Could not find target off branch.");
                                    }
                                    branchTargetIdx++;
                                }

                                // start a new basic block from this branch on
                                BasicBlock tempNextBasicBlock = new BasicBlock(this.semanticId);
                                this.semanticId++;
                                this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref tempNextBasicBlock);

                                // add new basic block to branch targets
                                currentExitBranch.takenTarget.Add(tempNextBasicBlock);

                                counter++;
                            }

                            // start a new basic block directly after the switch instruction and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.notTakenTarget);

                            return;
                        }

                    // exception handler beginning or end (end of try block or catch block)
                    case OperationCode.Leave:
                    case OperationCode.Leave_S: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // calculate the target index of the branch
                            int branchTargetIdx = 0;
                            uint branchTargetOffset = (uint)operation.Value;
                            while (true) {
                                if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                    break;
                                }
                                else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                    throw new ArgumentException("Could not find target off branch.");
                                }
                                branchTargetIdx++;
                            }

                            // create new exit branch object
                            ExceptionBranchTarget currentExitBranch = new ExceptionBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.exceptionTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentExitBranch.exitTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start two new basic blocks from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.exceptionTarget);
                            this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref currentExitBranch.exitTarget);
                            return;
                        }

                    // create a virtual basic block at the end of a catch/finally handler
                    case OperationCode.Rethrow:
                    case OperationCode.Endfinally: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            NoBranchTarget currentExitBranch = new NoBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.takenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start a new basic block from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.takenTarget);

                            return;
                        }


                    default:
                        break;
                }
            }
        }
コード例 #5
0
        // insert the given new target basic block between the given conditional branch to manipulate
        public void insertBasicBlockBetweenBranch(ConditionalBranchTarget branchToManipulate, bool manipulateTakenBranch, BasicBlock newTarget, ConditionalBranchTarget exitBranch, bool useTakenBranch) {

            // get the basic block from that the branch is taken and the basic block to that the branch is taken
            BasicBlock introBasicBlock = branchToManipulate.sourceBasicBlock;
            BasicBlock outroBasicBlock = null;

            // check wether to use the taken or not taken part of the exit branch
            if (useTakenBranch) {

                // check wether to manipulate the taken or not taken branch of the branch to manipulate
                if (manipulateTakenBranch) {
                    outroBasicBlock = branchToManipulate.takenTarget;
                    this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref exitBranch.takenTarget);
                }
                else {
                    outroBasicBlock = branchToManipulate.notTakenTarget;
                    this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.notTakenTarget, newTarget, newTarget, exitBranch, ref exitBranch.takenTarget);
                }


            }
            else {

                // check wether to manipulate the taken or not taken branch of the branch to manipulate
                if (manipulateTakenBranch) {
                    outroBasicBlock = branchToManipulate.takenTarget;
                    this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref exitBranch.notTakenTarget);
                }
                else {
                    outroBasicBlock = branchToManipulate.notTakenTarget;
                    this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.notTakenTarget, newTarget, newTarget, exitBranch, ref exitBranch.notTakenTarget);
                }
            }
        }
コード例 #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
        // 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);
            }

        }
コード例 #8
0
        // this function injects an opaque predicate to the target branch
        private void injectOpaquePredicateCode(CfgManipulator cfgManipulator, Target target, ref ConditionalBranchTarget opaqueExitBranch, IBranchTarget targetBranch, BasicBlockGraphNodeLink link, int currentValidPathId, int opaquePredicate, LocalDefinition currentNodeLocal) {

            // create "true" or "false" opaque predicate and add it to the code
            switch (opaquePredicate) {

                // "true" opaque predicate
                case 0: {
                        BasicBlock opaqueStartBasicBlock = null;

                        this.createCodeTruePredicate(ref opaqueStartBasicBlock, ref opaqueExitBranch, link, currentNodeLocal);

                        // inject target branch with opaque predicate
                        if ((targetBranch as SwitchBranchTarget) != null) {
                            SwitchBranchTarget tempTargetBranch = (targetBranch as SwitchBranchTarget);
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, currentValidPathId, opaqueStartBasicBlock, opaqueExitBranch, true);
                        }
                        else {
                            throw new ArgumentException("Not implemented yet.");
                        }

                        // set template semantic id of dead code basic block
                        BasicBlock deadCodeBasicBlock = opaqueExitBranch.notTakenTarget;
                        GraphTransformerDeadCodeBasicBlock deadCodeMetadata = (deadCodeBasicBlock.transformationMetadata.ElementAt(0) as GraphTransformerDeadCodeBasicBlock);
                        deadCodeMetadata.semanticId = target.basicBlock.semanticId;

                        break;
                    }

                // "false" opaque predicate
                case 1: {
                        BasicBlock opaqueStartBasicBlock = null;

                        this.createCodeFalsePredicate(ref opaqueStartBasicBlock, ref opaqueExitBranch, link, currentNodeLocal);

                        // inject target branch with opaque predicate
                        if ((targetBranch as SwitchBranchTarget) != null) {
                            SwitchBranchTarget tempTargetBranch = (targetBranch as SwitchBranchTarget);
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, currentValidPathId, opaqueStartBasicBlock, opaqueExitBranch, false);
                        }
                        else {
                            throw new ArgumentException("Not implemented yet.");
                        }

                        // set template semantic id of dead code basic block
                        BasicBlock deadCodeBasicBlock = opaqueExitBranch.takenTarget;
                        GraphTransformerDeadCodeBasicBlock deadCodeMetadata = (deadCodeBasicBlock.transformationMetadata.ElementAt(0) as GraphTransformerDeadCodeBasicBlock);
                        deadCodeMetadata.semanticId = target.basicBlock.semanticId;

                        break;
                    }

                // "Random" opaque predicate.
                case 2: {
                        BasicBlock opaqueStartBasicBlock = null;

                        if((targetBranch as SwitchBranchTarget) != null) {
                            SwitchBranchTarget tempTargetBranch = (targetBranch as SwitchBranchTarget);
                            var destinationBlock = tempTargetBranch.takenTarget[currentValidPathId];

                            this.createCodeRandomPredicate(ref opaqueStartBasicBlock, ref opaqueExitBranch, link, currentNodeLocal);

                            bool chooseBranch = prng.Next(1) == 0;
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, currentValidPathId, opaqueStartBasicBlock, opaqueExitBranch, chooseBranch);
                        }
                        else {
                            throw new ArgumentException("Not implemented yet.");
                        }
                        break;
                    }

                default:
                    throw new ArgumentException("This case should never be reached.");
            }

        }
コード例 #9
0
        // creates a duplicate of the given source basic block with the branch targets to semantically equivalent basic blocks
        // (not necessary the target basic block of the given source basic block)
        private BasicBlock duplicateBasicBlock(MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock sourceBasicBlock) {

            // search for a semantically equal basic block in the unmodified method CFG
            int searchSementicId = sourceBasicBlock.semanticId;
            BasicBlock copiedOriginalTargetBasicBlock = null;
            if (searchSementicId == -1) {
                throw new ArgumentException("No distinct semantic id given to search for.");
            }
            foreach (BasicBlock searchBasicBlock in originalMethodCfg.basicBlocks) {
                if (searchBasicBlock.semanticId == searchSementicId) {
                    copiedOriginalTargetBasicBlock = searchBasicBlock;
                    break;
                }
            }
            if (copiedOriginalTargetBasicBlock == null) {
                throw new ArgumentException("Not able to find semantically equal basic block in copied CFG.");
            }

            // create a new basic block
            BasicBlock newBasicBlock = new BasicBlock();

            // copy simple values
            newBasicBlock.semanticId = copiedOriginalTargetBasicBlock.semanticId;
            newBasicBlock.startIdx = copiedOriginalTargetBasicBlock.startIdx;
            newBasicBlock.endIdx = copiedOriginalTargetBasicBlock.endIdx;

            // copy all operations of the basic block
            foreach (IOperation operation in copiedOriginalTargetBasicBlock.operations) {
                newBasicBlock.operations.Add(this.helperClass.createNewOperation(operation.OperationCode, operation.Value, operation.Location, operation.Offset));
            }

            if (copiedOriginalTargetBasicBlock.tryBlocks.Count() != 0
                || copiedOriginalTargetBasicBlock.handlerBlocks.Count() != 0) {
                throw new ArgumentException("Not implemented yet.");
            }

            // create an exit branch for the new basic block
            if ((copiedOriginalTargetBasicBlock.exitBranch as NoBranchTarget) != null) {

                //throw new ArgumentException("Not implemented yet."); // TODO: problem here with having 2 no branches before a basic block (but not necessarily because all branches are processed and exchanged)

                NoBranchTarget exitBranch = (copiedOriginalTargetBasicBlock.exitBranch as NoBranchTarget);

                // create a copied exit branch
                NoBranchTarget copiedExitBranch = new NoBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                searchSementicId = exitBranch.takenTarget.semanticId;
                List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                BasicBlock targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.takenTarget = targetBasicBlock;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as UnconditionalBranchTarget != null) {
                UnconditionalBranchTarget exitBranch = (copiedOriginalTargetBasicBlock.exitBranch as UnconditionalBranchTarget);

                // create a copied exit branch
                UnconditionalBranchTarget copiedExitBranch = new UnconditionalBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                searchSementicId = exitBranch.takenTarget.semanticId;
                List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                BasicBlock targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.takenTarget = targetBasicBlock;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ConditionalBranchTarget != null) {
                ConditionalBranchTarget exitBranch = (copiedOriginalTargetBasicBlock.exitBranch as ConditionalBranchTarget);

                // create a copied exit branch
                ConditionalBranchTarget copiedExitBranch = new ConditionalBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets) (for "taken" branch)
                searchSementicId = exitBranch.takenTarget.semanticId;
                List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                BasicBlock targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.takenTarget = targetBasicBlock;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets) (for "not taken" branch)
                searchSementicId = exitBranch.notTakenTarget.semanticId;
                possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.notTakenTarget = targetBasicBlock;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as SwitchBranchTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ExitBranchTarget != null) {

                // create a copied exit branch
                ExitBranchTarget copiedExitBranch = new ExitBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ThrowBranchTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as TryBlockTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ExceptionBranchTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else {
                throw new ArgumentException("Do not know how to handle exit branch.");
            }

            return newBasicBlock;

        }
コード例 #10
0
        // this function generates code for an opaque predicate that evaluates to "true"
        // => the "taken" branch of the conditional branch have to be taken for the correct code path
        private void createCodeTruePredicate(ref BasicBlock outStartBasicBlock, ref ConditionalBranchTarget outConditionalBranch,
            BasicBlockGraphNodeLink link, LocalDefinition currentNodeLocal) {

            // create a basic block that checks the opaque predicate (this check evaluates to "true")
            BasicBlock startBasicBlock = new BasicBlock();
            startBasicBlock.startIdx = 0;
            startBasicBlock.endIdx = 0;

            // add graph transformer metadata to the basic block
            GraphTransformerPredicateBasicBlock metadata = new GraphTransformerPredicateBasicBlock();
            metadata.predicateType = GraphOpaquePredicate.True;
            metadata.correspondingGraphNodes.Add(link);
            startBasicBlock.transformationMetadata.Add(metadata);

            // search for the valid and invalid interfaces list of the current valid path id
            List<ITypeReference> validInterfaces = null;
            List<ITypeReference> invalidInterfaces = null;
            foreach (PathElement pathElement in link.graphNode.pathElements) {
                if (pathElement.validPathId == link.validPathId) {
                    validInterfaces = pathElement.validInterfaces;
                    invalidInterfaces = pathElement.invalidInterfaces;
                }
            }
            if (validInterfaces == null
                || invalidInterfaces == null) {
                throw new ArgumentException("No valid/invalid interface list was found.");
            }

            emitPredicateCode(startBasicBlock, currentNodeLocal, validInterfaces, invalidInterfaces);

            // create the conditional branch for the checking basic block (taken => correct code; not taken => dead code)
            ConditionalBranchTarget startBasicBlockExitBranch = new ConditionalBranchTarget();
            startBasicBlockExitBranch.sourceBasicBlock = startBasicBlock;
            startBasicBlock.exitBranch = startBasicBlockExitBranch;

            // create the dead code for this opaque predicate
            BasicBlock deadCodeBasicBlock = new BasicBlock();
            deadCodeBasicBlock.startIdx = 0;
            deadCodeBasicBlock.endIdx = 0;

            // set the dead code basic block as "not taken" target for the conditional branch of the checking basic block
            deadCodeBasicBlock.entryBranches.Add(startBasicBlockExitBranch);
            startBasicBlockExitBranch.notTakenTarget = deadCodeBasicBlock;

            // generate dead code for the dead code basic block
            GraphTransformerDeadCodeBasicBlock deadCodeMetadata = new GraphTransformerDeadCodeBasicBlock();
            deadCodeBasicBlock.transformationMetadata.Add(deadCodeMetadata);

            // set the created basic block and conditional jumps as output
            outStartBasicBlock = startBasicBlock;
            outConditionalBranch = startBasicBlockExitBranch;

        }
コード例 #11
0
 // Generates code for an opaque predicate evaluating to a random value.
 // => Both branches point to basic blocks with equal semantics.
 private void createCodeRandomPredicate(ref BasicBlock outStartBasicBlock, ref ConditionalBranchTarget outConditionalBranch,
     BasicBlockGraphNodeLink link, LocalDefinition currentNodeLocal)
 {
     throw new ArgumentException("Not implemented."); // TODO: will improve the probabilistic control flow
 }
コード例 #12
0
        // this function generates code for an opaque predicate that evaluates to "false"
        // => the "not taken" branch of the conditional branch have to be taken for the correct code path
        private void createCodeFalsePredicate(ref BasicBlock outStartBasicBlock, ref ConditionalBranchTarget outConditionalBranch, BasicBlockGraphNodeLink link, LocalDefinition currentNodeLocal) {

            // create a basic block that checks the opaque predicate (this check evaluates to "false")
            BasicBlock startBasicBlock = new BasicBlock();
            startBasicBlock.startIdx = 0;
            startBasicBlock.endIdx = 0;

            // add graph transformer metadata to the basic block
            GraphTransformerPredicateBasicBlock metadata = new GraphTransformerPredicateBasicBlock();
            metadata.predicateType = GraphOpaquePredicate.False;
            metadata.correspondingGraphNodes.Add(link);
            startBasicBlock.transformationMetadata.Add(metadata);

            // search for the valid and invalid interfaces list of the current valid path id
            List<ITypeReference> validInterfaces = null;
            List<ITypeReference> invalidInterfaces = null;
            foreach (PathElement pathElement in link.graphNode.pathElements) {
                if (pathElement.validPathId == link.validPathId) {
                    validInterfaces = pathElement.validInterfaces;
                    invalidInterfaces = pathElement.invalidInterfaces;
                }
            }
            if(validInterfaces == null
                || invalidInterfaces == null) {
                    throw new ArgumentException("No valid/invalid interface list was found.");
            }

            // add a random check to the code
            // important: for this predicate the dead code is reached by the "taken" branch and the correct code is reached by the "not taken" branch
            int randPosition;
            ITypeReference interfaceToCheck = null;
            switch (this.prng.Next(8)) {
                case 0:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

                case 1:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 2:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_1));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

                case 3:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 4:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 5:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

                case 6:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_1));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 7:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

                default:
                    throw new ArgumentException("This case should never be reached.");
            }

            // create the conditional branch for the checking basic block (not taken => correct code; taken => dead code)
            ConditionalBranchTarget startBasicBlockExitBranch = new ConditionalBranchTarget();
            startBasicBlockExitBranch.sourceBasicBlock = startBasicBlock;
            startBasicBlock.exitBranch = startBasicBlockExitBranch;


            // create the dead code for this opaque predicate
            BasicBlock deadCodeBasicBlock = new BasicBlock();
            deadCodeBasicBlock.startIdx = 0;
            deadCodeBasicBlock.endIdx = 0;

            // set the dead code basic block as "taken" target for the conditional branch of the checking basic block
            deadCodeBasicBlock.entryBranches.Add(startBasicBlockExitBranch);
            startBasicBlockExitBranch.takenTarget = deadCodeBasicBlock;

            // generate dead code for the dead code basic block
            GraphTransformerDeadCodeBasicBlock deadCodeMetadata = new GraphTransformerDeadCodeBasicBlock();
            deadCodeBasicBlock.transformationMetadata.Add(deadCodeMetadata);

            // set the created basic block and conditional jumps as output
            outStartBasicBlock = startBasicBlock;
            outConditionalBranch = startBasicBlockExitBranch;

        }