Files
heroims-obfuscator/llvm/lib/Transforms/Obfuscation/BogusControlFlow.cpp
T
heroims 2d2edd27e0 init
2022-04-11 17:27:31 +08:00

696 lines
29 KiB
C++

//===- BogusControlFlow.cpp - BogusControlFlow Obfuscation pass ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
//
// This file implements BogusControlFlow's pass, inserting bogus control flow.
// It adds bogus flow to a given basic block this way:
//
// Before :
// entry
// |
// ______v______
// | Original |
// |_____________|
// |
// v
// return
//
// After :
// entry
// |
// ____v_____
// |condition*| (false)
// |__________|----+
// (true)| |
// | |
// ______v______ |
// +-->| Original* | |
// | |_____________| (true)
// | (false)| !-----------> return
// | ______v______ |
// | | Altered |<--!
// | |_____________|
// |__________|
//
// * The results of these terminator's branch's conditions are always true, but
// these predicates are
// opacificated. For this, we declare two global values: x and y, and replace
// the FCMP_TRUE predicate with (y < 10 || x * (x + 1) % 2 == 0) (this could
// be improved, as the global values give a hint on where are the opaque
// predicates)
//
// The altered bloc is a copy of the original's one with junk instructions
// added accordingly to the type of instructions we found in the bloc
//
// Each basic block of the function is choosen if a random number in the range
// [0,100] is smaller than the choosen probability rate. The default value
// is 30. This value can be modify using the option -boguscf-prob=[value].
// Value must be an integer in the range [0, 100], otherwise the default value
// is taken. Exemple: -bcf -bcf_prob=60
//
// The pass can also be loop many times on a function, including on the basic
// blocks added in a previous loop. Be careful if you use a big probability
// number and choose to run the loop many times wich may cause the pass to run
// for a very long time. The default value is one loop, but you can change it
// with -boguscf-loop=[value]. Value must be an integer greater than 1,
// otherwise the default value is taken. Exemple: -bcf -bcf_loop=2
//
//
// Defined debug types:
// - "gen" : general informations
// - "opt" : concerning the given options (parameter)
// - "cfg" : printing the various function's cfg before transformation
// and after transformation if it has been modified, and all
// the functions at end of the pass, after doFinalization.
//
// To use them all, simply use the -debug option.
// To use only one of them, follow the pass' command by -debug-only=name.
// Exemple, -bcf -debug-only=cfg
//
//
// Stats:
// The following statistics will be printed if you use
// the -stats command:
//
// a. Number of functions in this module
// b. Number of times we run on each function
// c. Initial number of basic blocks in this module
// d. Number of modified basic blocks
// e. Number of added basic blocks in this module
// f. Final number of basic blocks in this module
//
// file : lib/Transforms/Obfuscation/BogusControlFlow.cpp
// date : june 2012
// version: 1.0
// author : julie.michielin@gmail.com
// modifications: pjunod, Rinaldini Julien
// project: Obfuscator
// option : -bcf
//
//===---------------------------------------------------------------------===//
#include "llvm/Transforms/Obfuscation/BogusControlFlow.h"
#include "llvm/Transforms/Obfuscation/Utils.h"
// Stats
#define DEBUG_TYPE "BogusControlFlow"
STATISTIC(NumFunction, "a. Number of functions in this module");
STATISTIC(NumTimesOnFunctions, "b. Number of times we run on each function");
STATISTIC(InitNumBasicBlocks,
"c. Initial number of basic blocks in this module");
STATISTIC(NumModifiedBasicBlocks, "d. Number of modified basic blocks");
STATISTIC(NumAddedBasicBlocks,
"e. Number of added basic blocks in this module");
STATISTIC(FinalNumBasicBlocks,
"f. Final number of basic blocks in this module");
using namespace llvm;
// Options for the pass
const int defaultObfRate = 30, defaultObfTime = 1;
static cl::opt<int>
ObfProbRate("bcf_prob",
cl::desc("Choose the probability [%] each basic blocks will be "
"obfuscated by the -bcf pass"),
cl::value_desc("probability rate"), cl::init(defaultObfRate),
cl::Optional);
static cl::opt<int>
ObfTimes("bcf_loop",
cl::desc("Choose how many time the -bcf pass loop on a function"),
cl::value_desc("number of times"), cl::init(defaultObfTime),
cl::Optional);
namespace {
struct BogusControlFlow : public FunctionPass {
static char ID; // Pass identification
bool flag;
BogusControlFlow() : FunctionPass(ID) {}
BogusControlFlow(bool flag) : FunctionPass(ID) {
this->flag = flag;
BogusControlFlow();
}
/* runOnFunction
*
* Overwrite FunctionPass method to apply the transformation
* to the function. See header for more details.
*/
virtual bool runOnFunction(Function &F) {
// If fla annotations
if (toObfuscate(flag, &F, "bcf")) {
return runOnCustomFunction(F);
}
return false;
} // end of runOnFunction()
bool runOnCustomFunction(Function &F) {
if (ObfTimes <= 0) {
errs() << "BogusControlFlow application number -bcf_loop=x must be x > 0";
return false;
}
// Check if the number of applications is correct
if (!((ObfProbRate > 0) && (ObfProbRate <= 100))) {
errs() << "BogusControlFlow application basic blocks percentage "
"-bcf_prob=x must be 0 < x <= 100";
return false;
}
bogus(F);
doF(*F.getParent());
return true;
} // end of runOnFunction()
void bogus(Function &F) {
// For statistics and debug
++NumFunction;
int NumBasicBlocks = 0;
bool firstTime = true; // First time we do the loop in this function
bool hasBeenModified = false;
DEBUG_WITH_TYPE("opt", errs() << "bcf: Started on function " << F.getName()
<< "\n");
DEBUG_WITH_TYPE("opt",
errs() << "bcf: Probability rate: " << ObfProbRate << "\n");
if (ObfProbRate < 0 || ObfProbRate > 100) {
DEBUG_WITH_TYPE("opt", errs()
<< "bcf: Incorrect value,"
<< " probability rate set to default value: "
<< defaultObfRate << " \n");
ObfProbRate = defaultObfRate;
}
DEBUG_WITH_TYPE("opt", errs()
<< "bcf: How many times: " << ObfTimes << "\n");
if (ObfTimes <= 0) {
DEBUG_WITH_TYPE("opt", errs()
<< "bcf: Incorrect value,"
<< " must be greater than 1. Set to default: "
<< defaultObfTime << " \n");
ObfTimes = defaultObfTime;
}
NumTimesOnFunctions = ObfTimes;
int NumObfTimes = ObfTimes;
// Real begining of the pass
// Loop for the number of time we run the pass on the function
do {
DEBUG_WITH_TYPE("cfg", errs() << "bcf: Function " << F.getName()
<< ", before the pass:\n");
DEBUG_WITH_TYPE("cfg", F.viewCFG());
// Put all the function's block in a list
std::list<BasicBlock *> basicBlocks;
for (Function::iterator i = F.begin(); i != F.end(); ++i) {
if (!i->isEHPad())
basicBlocks.push_back(&*i);
}
DEBUG_WITH_TYPE(
"gen", errs() << "bcf: Iterating on the Function's Basic Blocks\n");
while (!basicBlocks.empty()) {
NumBasicBlocks++;
// Basic Blocks' selection
if ((int)llvm::cryptoutils->get_range(100) <= ObfProbRate) {
DEBUG_WITH_TYPE("opt", errs() << "bcf: Block " << NumBasicBlocks
<< " selected. \n");
hasBeenModified = true;
++NumModifiedBasicBlocks;
NumAddedBasicBlocks += 3;
FinalNumBasicBlocks += 3;
// Add bogus flow to the given Basic Block (see description)
BasicBlock *basicBlock = basicBlocks.front();
addBogusFlow(basicBlock, F);
} else {
DEBUG_WITH_TYPE("opt", errs() << "bcf: Block " << NumBasicBlocks
<< " not selected.\n");
}
// remove the block from the list
basicBlocks.pop_front();
if (firstTime) { // first time we iterate on this function
++InitNumBasicBlocks;
++FinalNumBasicBlocks;
}
} // end of while(!basicBlocks.empty())
DEBUG_WITH_TYPE("gen",
errs() << "bcf: End of function " << F.getName() << "\n");
if (hasBeenModified) { // if the function has been modified
DEBUG_WITH_TYPE("cfg", errs() << "bcf: Function " << F.getName()
<< ", after the pass: \n");
DEBUG_WITH_TYPE("cfg", F.viewCFG());
} else {
DEBUG_WITH_TYPE("cfg", errs()
<< "bcf: Function's not been modified \n");
}
firstTime = false;
} while (--NumObfTimes > 0);
}
/* addBogusFlow
*
* Add bogus flow to a given basic block, according to the header's
* description
*/
virtual void addBogusFlow(BasicBlock *basicBlock, Function &F) {
// Split the block: first part with only the phi nodes and debug info and
// terminator
// created by splitBasicBlock. (-> No instruction)
// Second part with every instructions from the original
// block
// We do this way, so we don't have to adjust all the phi nodes, metadatas
// and so on for the first block. We have to let the phi nodes in the first
// part, because they actually are updated in the second part according to
// them.
BasicBlock::iterator i1 = basicBlock->begin();
if (basicBlock->getFirstNonPHIOrDbgOrLifetime())
i1 = (BasicBlock::iterator)basicBlock->getFirstNonPHIOrDbgOrLifetime();
Twine *var;
var = new Twine("originalBB");
BasicBlock *originalBB = basicBlock->splitBasicBlock(i1, *var);
DEBUG_WITH_TYPE("gen", errs()
<< "bcf: First and original basic blocks: ok\n");
// Creating the altered basic block on which the first basicBlock will jump
Twine *var3 = new Twine("alteredBB");
BasicBlock *alteredBB = createAlteredBasicBlock(originalBB, *var3, &F);
DEBUG_WITH_TYPE("gen", errs() << "bcf: Altered basic block: ok\n");
// Now that all the blocks are created,
// we modify the terminators to adjust the control flow.
alteredBB->getTerminator()->eraseFromParent();
basicBlock->getTerminator()->eraseFromParent();
DEBUG_WITH_TYPE("gen", errs() << "bcf: Terminator removed from the altered"
<< " and first basic blocks\n");
// Preparing a condition..
// For now, the condition is an always true comparaison between 2 float
// This will be complicated after the pass (in doFinalization())
Value *LHS = ConstantFP::get(Type::getFloatTy(F.getContext()), 1.0);
Value *RHS = ConstantFP::get(Type::getFloatTy(F.getContext()), 1.0);
DEBUG_WITH_TYPE("gen", errs() << "bcf: Value LHS and RHS created\n");
// The always true condition. End of the first block
Twine *var4 = new Twine("condition");
FCmpInst *condition =
new FCmpInst(*basicBlock, FCmpInst::FCMP_TRUE, LHS, RHS, *var4);
DEBUG_WITH_TYPE("gen", errs() << "bcf: Always true condition created\n");
// Jump to the original basic block if the condition is true or
// to the altered block if false.
BranchInst::Create(originalBB, alteredBB, (Value *)condition, basicBlock);
DEBUG_WITH_TYPE(
"gen",
errs() << "bcf: Terminator instruction in first basic block: ok\n");
// The altered block loop back on the original one.
BranchInst::Create(originalBB, alteredBB);
DEBUG_WITH_TYPE(
"gen", errs() << "bcf: Terminator instruction in altered block: ok\n");
// The end of the originalBB is modified to give the impression that
// sometimes it continues in the loop, and sometimes it return the desired
// value (of course it's always true, so it always use the original
// terminator..
// but this will be obfuscated too;) )
// iterate on instruction just before the terminator of the originalBB
BasicBlock::iterator i = originalBB->end();
// Split at this point (we only want the terminator in the second part)
Twine *var5 = new Twine("originalBBpart2");
BasicBlock *originalBBpart2 = originalBB->splitBasicBlock(--i, *var5);
DEBUG_WITH_TYPE("gen",
errs() << "bcf: Terminator part of the original basic block"
<< " is isolated\n");
// the first part go either on the return statement or on the begining
// of the altered block.. So we erase the terminator created when splitting.
originalBB->getTerminator()->eraseFromParent();
// We add at the end a new always true condition
Twine *var6 = new Twine("condition2");
FCmpInst *condition2 =
new FCmpInst(*originalBB, CmpInst::FCMP_TRUE, LHS, RHS, *var6);
BranchInst::Create(originalBBpart2, alteredBB, (Value *)condition2,
originalBB);
DEBUG_WITH_TYPE("gen", errs()
<< "bcf: Terminator original basic block: ok\n");
DEBUG_WITH_TYPE("gen", errs() << "bcf: End of addBogusFlow().\n");
} // end of addBogusFlow()
/* createAlteredBasicBlock
*
* This function return a basic block similar to a given one.
* It's inserted just after the given basic block.
* The instructions are similar but junk instructions are added between
* the cloned one. The cloned instructions' phi nodes, metadatas, uses and
* debug locations are adjusted to fit in the cloned basic block and
* behave nicely.
*/
virtual BasicBlock *createAlteredBasicBlock(BasicBlock *basicBlock,
const Twine &Name = "gen",
Function *F = 0) {
// Useful to remap the informations concerning instructions.
ValueToValueMapTy VMap;
BasicBlock *alteredBB = llvm::CloneBasicBlock(basicBlock, VMap, Name, F);
DEBUG_WITH_TYPE("gen", errs() << "bcf: Original basic block cloned\n");
// Remap operands.
BasicBlock::iterator ji = basicBlock->begin();
for (BasicBlock::iterator i = alteredBB->begin(), e = alteredBB->end();
i != e; ++i) {
// Loop over the operands of the instruction
for (User::op_iterator opi = i->op_begin(), ope = i->op_end(); opi != ope;
++opi) {
// get the value for the operand
Value *v = MapValue(*opi, VMap, RF_None, 0);
if (v != 0) {
*opi = v;
DEBUG_WITH_TYPE("gen",
errs() << "bcf: Value's operand has been setted\n");
}
}
DEBUG_WITH_TYPE("gen", errs() << "bcf: Operands remapped\n");
// Remap phi nodes' incoming blocks.
if (PHINode *pn = dyn_cast<PHINode>(i)) {
for (unsigned j = 0, e = pn->getNumIncomingValues(); j != e; ++j) {
Value *v = MapValue(pn->getIncomingBlock(j), VMap, RF_None, 0);
if (v != 0) {
pn->setIncomingBlock(j, cast<BasicBlock>(v));
}
}
}
DEBUG_WITH_TYPE("gen", errs() << "bcf: PHINodes remapped\n");
// Remap attached metadata.
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
i->getAllMetadata(MDs);
DEBUG_WITH_TYPE("gen", errs() << "bcf: Metadatas remapped\n");
// important for compiling with DWARF, using option -g.
i->setDebugLoc(ji->getDebugLoc());
ji++;
DEBUG_WITH_TYPE("gen", errs()
<< "bcf: Debug information location setted\n");
} // The instructions' informations are now all correct
DEBUG_WITH_TYPE("gen",
errs() << "bcf: The cloned basic block is now correct\n");
DEBUG_WITH_TYPE(
"gen",
errs() << "bcf: Starting to add junk code in the cloned bloc...\n");
// add random instruction in the middle of the bloc. This part can be
// improve
for (BasicBlock::iterator i = alteredBB->begin(), e = alteredBB->end();
i != e; ++i) {
// in the case we find binary operator, we modify slightly this part by
// randomly insert some instructions
if (i->isBinaryOp()) { // binary instructions
unsigned opcode = i->getOpcode();
BinaryOperator *op, *op1 = NULL;
UnaryOperator *op2;
Twine *var = new Twine("_");
// treat differently float or int
// Binary int
if (opcode == Instruction::Add || opcode == Instruction::Sub ||
opcode == Instruction::Mul || opcode == Instruction::UDiv ||
opcode == Instruction::SDiv || opcode == Instruction::URem ||
opcode == Instruction::SRem || opcode == Instruction::Shl ||
opcode == Instruction::LShr || opcode == Instruction::AShr ||
opcode == Instruction::And || opcode == Instruction::Or ||
opcode == Instruction::Xor) {
for (int random = (int)llvm::cryptoutils->get_range(10); random < 10;
++random) {
switch (llvm::cryptoutils->get_range(4)) { // to improve
case 0: // do nothing
break;
case 1:
op = BinaryOperator::CreateNeg(i->getOperand(0), *var, &*i);
op1 = BinaryOperator::Create(Instruction::Add, op,
i->getOperand(1), "gen", &*i);
break;
case 2:
op1 = BinaryOperator::Create(Instruction::Sub, i->getOperand(0),
i->getOperand(1), *var, &*i);
op = BinaryOperator::Create(Instruction::Mul, op1,
i->getOperand(1), "gen", &*i);
break;
case 3:
op = BinaryOperator::Create(Instruction::Shl, i->getOperand(0),
i->getOperand(1), *var, &*i);
break;
}
}
}
// Binary float
if (opcode == Instruction::FAdd || opcode == Instruction::FSub ||
opcode == Instruction::FMul || opcode == Instruction::FDiv ||
opcode == Instruction::FRem) {
for (int random = (int)llvm::cryptoutils->get_range(10); random < 10;
++random) {
switch (llvm::cryptoutils->get_range(3)) { // can be improved
case 0: // do nothing
break;
case 1:
op2 = UnaryOperator::CreateFNeg(i->getOperand(0),*var,&*i);
op1 = BinaryOperator::Create(Instruction::FAdd,op2,
i->getOperand(1),"gen",&*i);
break;
case 2:
op = BinaryOperator::Create(Instruction::FSub, i->getOperand(0),
i->getOperand(1), *var, &*i);
op1 = BinaryOperator::Create(Instruction::FMul, op,
i->getOperand(1), "gen", &*i);
break;
}
}
}
if (opcode == Instruction::ICmp) { // Condition (with int)
ICmpInst *currentI = (ICmpInst *)(&i);
switch (llvm::cryptoutils->get_range(3)) { // must be improved
case 0: // do nothing
break;
case 1:
currentI->swapOperands();
break;
case 2: // randomly change the predicate
switch (llvm::cryptoutils->get_range(10)) {
case 0:
currentI->setPredicate(ICmpInst::ICMP_EQ);
break; // equal
case 1:
currentI->setPredicate(ICmpInst::ICMP_NE);
break; // not equal
case 2:
currentI->setPredicate(ICmpInst::ICMP_UGT);
break; // unsigned greater than
case 3:
currentI->setPredicate(ICmpInst::ICMP_UGE);
break; // unsigned greater or equal
case 4:
currentI->setPredicate(ICmpInst::ICMP_ULT);
break; // unsigned less than
case 5:
currentI->setPredicate(ICmpInst::ICMP_ULE);
break; // unsigned less or equal
case 6:
currentI->setPredicate(ICmpInst::ICMP_SGT);
break; // signed greater than
case 7:
currentI->setPredicate(ICmpInst::ICMP_SGE);
break; // signed greater or equal
case 8:
currentI->setPredicate(ICmpInst::ICMP_SLT);
break; // signed less than
case 9:
currentI->setPredicate(ICmpInst::ICMP_SLE);
break; // signed less or equal
}
break;
}
}
if (opcode == Instruction::FCmp) { // Conditions (with float)
FCmpInst *currentI = (FCmpInst *)(&i);
switch (llvm::cryptoutils->get_range(3)) { // must be improved
case 0: // do nothing
break;
case 1:
currentI->swapOperands();
break;
case 2: // randomly change the predicate
switch (llvm::cryptoutils->get_range(10)) {
case 0:
currentI->setPredicate(FCmpInst::FCMP_OEQ);
break; // ordered and equal
case 1:
currentI->setPredicate(FCmpInst::FCMP_ONE);
break; // ordered and operands are unequal
case 2:
currentI->setPredicate(FCmpInst::FCMP_UGT);
break; // unordered or greater than
case 3:
currentI->setPredicate(FCmpInst::FCMP_UGE);
break; // unordered, or greater than, or equal
case 4:
currentI->setPredicate(FCmpInst::FCMP_ULT);
break; // unordered or less than
case 5:
currentI->setPredicate(FCmpInst::FCMP_ULE);
break; // unordered, or less than, or equal
case 6:
currentI->setPredicate(FCmpInst::FCMP_OGT);
break; // ordered and greater than
case 7:
currentI->setPredicate(FCmpInst::FCMP_OGE);
break; // ordered and greater than or equal
case 8:
currentI->setPredicate(FCmpInst::FCMP_OLT);
break; // ordered and less than
case 9:
currentI->setPredicate(FCmpInst::FCMP_OLE);
break; // ordered or less than, or equal
}
break;
}
}
}
}
return alteredBB;
} // end of createAlteredBasicBlock()
/* doFinalization
*
* Overwrite FunctionPass method to apply the transformations to the whole
* module. This part obfuscate all the always true predicates of the module.
* More precisely, the condition which predicate is FCMP_TRUE.
* It also remove all the functions' basic blocks' and instructions' names.
*/
bool doF(Module &M) {
// In this part we extract all always-true predicate and replace them with
// opaque predicate: For this, we declare two global values: x and y, and
// replace the FCMP_TRUE predicate with (y < 10 || x * (x + 1) % 2 == 0) A
// better way to obfuscate the predicates would be welcome. In the meantime
// we will erase the name of the basic blocks, the instructions and the
// functions.
DEBUG_WITH_TYPE("gen", errs() << "bcf: Starting doFinalization...\n");
// The global values
Twine *varX = new Twine("x");
Twine *varY = new Twine("y");
Value *x1 = ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false);
Value *y1 = ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false);
GlobalVariable *x =
new GlobalVariable(M, Type::getInt32Ty(M.getContext()), false,
GlobalValue::CommonLinkage, (Constant *)x1, *varX);
GlobalVariable *y =
new GlobalVariable(M, Type::getInt32Ty(M.getContext()), false,
GlobalValue::CommonLinkage, (Constant *)y1, *varY);
std::vector<Instruction *> toEdit, toDelete;
BinaryOperator *op, *op1 = NULL;
LoadInst *opX, *opY;
ICmpInst *condition, *condition2;
// Looking for the conditions and branches to transform
for (Module::iterator mi = M.begin(), me = M.end(); mi != me; ++mi) {
for (Function::iterator fi = mi->begin(), fe = mi->end(); fi != fe;
++fi) {
// fi->setName("");
Instruction *tbb = fi->getTerminator();
if (tbb->getOpcode() == Instruction::Br) {
BranchInst *br = (BranchInst *)(tbb);
if (br->isConditional()) {
FCmpInst *cond = (FCmpInst *)br->getCondition();
unsigned opcode = cond->getOpcode();
if (opcode == Instruction::FCmp) {
if (cond->getPredicate() == FCmpInst::FCMP_TRUE) {
DEBUG_WITH_TYPE("gen",
errs() << "bcf: an always true predicate !\n");
toDelete.push_back(cond); // The condition
toEdit.push_back(tbb); // The branch using the condition
}
}
}
}
/*
for (BasicBlock::iterator bi = fi->begin(), be = fi->end() ; bi != be;
++bi){ bi->setName(""); // setting the basic blocks' names
}
*/
}
}
// Replacing all the branches we found
for (std::vector<Instruction *>::iterator i = toEdit.begin();
i != toEdit.end(); ++i) {
// if y < 10 || x*(x+1) % 2 == 0
opX = new LoadInst(x->getType()->getElementType(), (Value *)x, "", (*i));
opY = new LoadInst(y->getType()->getElementType(), (Value *)y, "", (*i));
op = BinaryOperator::Create(
Instruction::Sub, (Value *)opX,
ConstantInt::get(Type::getInt32Ty(M.getContext()), 1, false), "",
(*i));
op1 =
BinaryOperator::Create(Instruction::Mul, (Value *)opX, op, "", (*i));
op = BinaryOperator::Create(
Instruction::URem, op1,
ConstantInt::get(Type::getInt32Ty(M.getContext()), 2, false), "",
(*i));
condition = new ICmpInst(
(*i), ICmpInst::ICMP_EQ, op,
ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false));
condition2 = new ICmpInst(
(*i), ICmpInst::ICMP_SLT, opY,
ConstantInt::get(Type::getInt32Ty(M.getContext()), 10, false));
op1 = BinaryOperator::Create(Instruction::Or, (Value *)condition,
(Value *)condition2, "", (*i));
BranchInst::Create(((BranchInst *)*i)->getSuccessor(0),
((BranchInst *)*i)->getSuccessor(1), (Value *)op1,
((BranchInst *)*i)->getParent());
DEBUG_WITH_TYPE("gen", errs() << "bcf: Erase branch instruction:"
<< *((BranchInst *)*i) << "\n");
(*i)->eraseFromParent(); // erase the branch
}
// Erase all the associated conditions we found
for (std::vector<Instruction *>::iterator i = toDelete.begin();
i != toDelete.end(); ++i) {
DEBUG_WITH_TYPE("gen", errs() << "bcf: Erase condition instruction:"
<< *((Instruction *)*i) << "\n");
(*i)->eraseFromParent();
}
// Only for debug
DEBUG_WITH_TYPE("cfg", errs() << "bcf: End of the pass, here are the "
"graphs after doFinalization\n");
for (Module::iterator mi = M.begin(), me = M.end(); mi != me; ++mi) {
DEBUG_WITH_TYPE("cfg", errs()
<< "bcf: Function " << mi->getName() << "\n");
DEBUG_WITH_TYPE("cfg", mi->viewCFG());
}
return true;
} // end of doFinalization
}; // end of struct BogusControlFlow : public FunctionPass
} // namespace
char BogusControlFlow::ID = 0;
static RegisterPass<BogusControlFlow> X("boguscf",
"inserting bogus control flow");
Pass *llvm::createBogus() { return new BogusControlFlow(); }
Pass *llvm::createBogus(bool flag) { return new BogusControlFlow(flag); }
PreservedAnalyses BogusControlFlowPass::run(Function& F, FunctionAnalysisManager& AM) {
BogusControlFlow bcf;
if (bcf.runOnCustomFunction(F))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}