Shuzheng Shuzheng - 4 years ago 104
C++ Question

How to fix this `FunctionPass` such that it doesn't go into an infinite loop?

The following code is an attempt to create a

FunctionPass
that iterates over all
BasicBlock
's, and change
a + b
into
(a xor b) + 2 * (a and b)
for obfuscation.

Now, when I use
ReplaceInstWithValue
the iterator gets invalidated and the program goes into an infinite loop.

I've tried several ways of fixing this, but none has proven useful.

How would I change the program, so that it iterates over ALL instructions in the program without going into an infinite loop on the first
add
instruction?

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <map>
#include <string>

using namespace llvm;

namespace {
struct CountOp : public FunctionPass {
std::map<std::string, int> bbNameToId;

static char ID;

CountOp() : FunctionPass(ID) {}

virtual bool runOnFunction(Function &F) {

for (Function::iterator bs = F.begin(), be = F.end(); bs != be; ++bs) {
for (BasicBlock::iterator is = bs->begin(), ie = be->end(); is != ie; ++is) {
Instruction& inst = *is;
BinaryOperator* binop = dyn_cast<BinaryOperator>(&inst);

if (!binop) {
continue;
}

unsigned opcode = binop->getOpcode();
errs() << binop->getOpcodeName() << "\n";

if (opcode != Instruction::Add) {
continue;
}

IRBuilder<> builder(binop);
Value* v = builder.CreateAdd(builder.CreateXor(binop->getOperand(0), binop->getOperand(1)),
builder.CreateMul(ConstantInt::get(binop->getType(), 2),
builder.CreateAnd(binop->getOperand(0), binop->getOperand(1))));

ReplaceInstWithValue(bs->getInstList(), is, v);
}
}


return true;
}
};
}

char CountOp::ID = 0;
static RegisterPass<CountOp> X("opChanger", "Change add operations", false, false);

Nze Nze
Answer Source

Actually, the problem is in the for statement:

for (BasicBlock::iterator is = bs->begin(), ie = be->end(); is != ie; ++is).

ie should be initialized to bs->end() and not be->end().

Then the example works fine.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download