void createUnconditionalBranch(BasicBlock deadCodeBasicBlock, ITransformationMetadata basicBlockMetadata) { // Branch to some other basic block in our method (or to a newly created dead code block). var exitBranch = new UnconditionalBranchTarget(); exitBranch.sourceBasicBlock = deadCodeBasicBlock; deadCodeBasicBlock.exitBranch = exitBranch; deadCodeBasicBlock.operations.Add(createNewOperation(OperationCode.Br, 0)); // TODO: Decrease possibility for dead code to be added? if (prng.Next(2) == 0) { // Random BB as dead code block target. var targetBlock = randomTargetBlock(); targetBlock.entryBranches.Add(exitBranch); exitBranch.takenTarget = targetBlock; } else { // New dead code BB as dead code block target. var targetBlock = new BasicBlock(); targetBlock.startIdx = targetBlock.endIdx = 0; targetBlock.entryBranches.Add(exitBranch); exitBranch.takenTarget = targetBlock; generateDeadCode(targetBlock, basicBlockMetadata); } }
// insert the given new target basic block (given by start and end block) between the given unconditional branch to manipulate public void insertBasicBlockBetweenBranch(UnconditionalBranchTarget branchToManipulate, 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 = branchToManipulate.takenTarget; this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTargetStart, newTargetEnd, exitBranch, ref exitBranch.takenTarget); }
// insert the given new target basic block between the given unconditional branch to manipulate public void insertBasicBlockBetweenBranch(UnconditionalBranchTarget branchToManipulate, 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 = branchToManipulate.takenTarget; // check wether to use the taken or not taken part of the exit branch if (useTakenBranch) { this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref exitBranch.takenTarget); } else { this.insertBasicBlockBetweenBranch(introBasicBlock, outroBasicBlock, branchToManipulate, ref branchToManipulate.takenTarget, newTarget, newTarget, exitBranch, ref exitBranch.notTakenTarget); } }
// insert the given new target basic block between the given conditional branch to manipulate public void insertBasicBlockBetweenBranch(UnconditionalBranchTarget branchToManipulate, 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 = 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; }
private void mutateRet(BasicBlock block, int index) { if (prng.Next(3) == 0) { return; } var exitBranch = new UnconditionalBranchTarget(); exitBranch.takenTarget = returnBlock; exitBranch.sourceBasicBlock = block; block.exitBranch = exitBranch; returnBlock.entryBranches.Add(exitBranch); var branchToReturn = createNewOperation(OperationCode.Br, 0); block.operations[index] = branchToReturn; block.semanticId = -1; }
// ################################################### SWITCH BRANCHES TO MANIPULATE ################################################### // insert the given new target basic block between the given switch branch to manipulate public void insertBasicBlockBetweenBranch(SwitchBranchTarget branchToManipulate, int manipulateTakenBranchIdx, BasicBlock newTarget, 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; 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; }
// 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); } }
// this function replaces a basic block inside the cfg (oldBasicBlock) with a construction of new basic blocks (newBasicBlockStart and newBasicBlockEnd) public void replaceBasicBlock(BasicBlock oldBasicBlock, BasicBlock newBasicBlockStart, BasicBlock newBasicBlockEnd) { // add new basic blocks to cfg this.addBasicBlockToCfgRecursively(newBasicBlockStart); // add entry branches that enter the old basic block to the new basic block newBasicBlockStart.entryBranches.AddRange(oldBasicBlock.entryBranches); // exchange the target of the entry branches from the old basic block to the new one foreach (IBranchTarget entryBranch in new List <IBranchTarget>(oldBasicBlock.entryBranches)) { if ((entryBranch as NoBranchTarget) != null) { NoBranchTarget tempEntryBranch = (entryBranch as NoBranchTarget); // check sanity of entry branch if (tempEntryBranch.takenTarget != oldBasicBlock) { throw new ArgumentException("Entry branch must have old basic block as target."); } // set new basic block as target tempEntryBranch.takenTarget = newBasicBlockStart; } else if ((entryBranch as UnconditionalBranchTarget) != null) { UnconditionalBranchTarget tempEntryBranch = (entryBranch as UnconditionalBranchTarget); // check sanity of entry branch if (tempEntryBranch.takenTarget != oldBasicBlock) { throw new ArgumentException("Entry branch must have old basic block as target."); } // set new basic block as target tempEntryBranch.takenTarget = newBasicBlockStart; } else if ((entryBranch as ConditionalBranchTarget) != null) { ConditionalBranchTarget tempEntryBranch = (entryBranch as ConditionalBranchTarget); bool sanity = false; // change all branches to the old basic block to the new basic block if (tempEntryBranch.takenTarget == oldBasicBlock) { tempEntryBranch.takenTarget = newBasicBlockStart; sanity = true; } if (tempEntryBranch.notTakenTarget == oldBasicBlock) { tempEntryBranch.notTakenTarget = newBasicBlockStart; sanity = true; } // check sanity of entry branch if (!sanity) { throw new ArgumentException("Entry branch must have old basic block as target."); } } else if ((entryBranch as SwitchBranchTarget) != null) { SwitchBranchTarget tempEntryBranch = (entryBranch as SwitchBranchTarget); bool sanity = false; // change all branches to the old basic block to the new basic block if (tempEntryBranch.notTakenTarget == oldBasicBlock) { tempEntryBranch.notTakenTarget = newBasicBlockStart; sanity = true; } for (int idx = 0; idx < tempEntryBranch.takenTarget.Count(); idx++) { if (tempEntryBranch.takenTarget.ElementAt(idx) == oldBasicBlock) { tempEntryBranch.takenTarget[idx] = newBasicBlockStart; sanity = true; } } // check sanity of entry branch if (!sanity) { throw new ArgumentException("Entry branch must have old basic block as target."); } } else { throw new ArgumentException("Not yet implemented."); } // remove entry branch from the old basic block entry branches list oldBasicBlock.entryBranches.Remove(entryBranch); } IBranchTarget exitBranch = oldBasicBlock.exitBranch; // change the exit branch of the old basic block to be the exit branch of the new one exitBranch.sourceBasicBlock = newBasicBlockEnd; newBasicBlockEnd.exitBranch = exitBranch; // check if the old basic block was the start basic block of the cfg // => change it to the new basic block if (this.methodCfg.startBasicBlock == oldBasicBlock) { this.methodCfg.startBasicBlock = newBasicBlockStart; } // remove old basic block if it still belongs to the cfg if (this.methodCfg.basicBlocks.Contains(oldBasicBlock)) { this.methodCfg.basicBlocks.Remove(oldBasicBlock); } }