2017-04-29 17:15:03 +04:00

135 строки
3.6 KiB
C++

#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/CommandLine.h"
#include "TypeValueSupport.h"
#include "BaseRandomizer.h"
#include <json/value.h>
#include "FlipConfig.h"
#include <iostream>
#include <map>
using namespace llvm;
extern cl::opt<std::string> ReplaceConfigFileName;
struct IntReplacerIterate: public ModulePass {
static char ID;
FlipConfig *_zConfig;
IntReplacerIterate() : ModulePass(ID)
{
_zConfig = new FlipConfig(ReplaceConfigFileName);
}
virtual bool
runOnModule(Module &M)
{
for (auto mIt = _zConfig->getReplaceMap().begin();
mIt != _zConfig->getReplaceMap().end(); ++mIt) {
std::string fnName = mIt->first;
FunctionConfig mFc = mIt->second;
if (mFc.shouldAnalyze == false) {
errs() << "Skipping analysis of " << fnName << " \n";
continue;
}
Function *f = M.getFunction(fnName);
if (f == NULL) {
continue;
}
for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) {
if (isa<CallInst>(&*I) || isa<InvokeInst>(&*I)) {
CallSite cs(&*I);
Function *called = cs.getCalledFunction();
if (!called->hasName()) {
continue; // XXX Currently require functions to have names
}
/*
* Determine if the call is of a function we don't want to replace args of..
*/
if (std::find(skip_replace_functions.begin(),
skip_replace_functions.end(),
called->getName()) != skip_replace_functions.end()) {
errs() << "Skipping: " << called->getName().str() << "\n";
continue; // Skip it.
}
/*
* Go through all the called function's arguments. See if
* any are supported by replacement.
*/
unsigned numArgOps = cs.getNumArgOperands();
for (unsigned ii = 0; ii < numArgOps; ii++) {
Value *va = cs.getArgOperand(ii);
Type *ta = va->getType();
/*
* If not a 8, 16, 32, or 64 bit integer, we skip it.
*/
if (TypeValueSupport::isReplaceable(ta, va) == false) {
continue;
}
/*
* Based on configuration, choose the randomization method.
*/
std::string rndtype = "";
if (mFc.randomType == 0) {
rndtype = "rep";
} else {
rndtype = "bitflip";
}
unsigned nBits = ta->getIntegerBitWidth();
std::string rndFnName = "__" + rndtype + "_randomizer_i" + std::to_string(nBits) + "__";
/*
* The randomizer functions /should/ already be in the module, so get the handle.
*/
Function *insertedRndFn = M.getFunction(rndFnName);
assert(insertedRndFn != NULL);
/*
* We allow different means for different functions.
*/
ConstantInt *mn = ConstantInt::get(M.getContext(), APInt(32, mFc.mean, false));
/*
* Insert call to randomizer with input integer and a mean value.
* It will be inserted before the CallInst.
*/
CallInst *callNewFunc = CallInst::Create(insertedRndFn,
{ va, mn }, // Arguments are the integer to maybe flip and the mean value
"__rnd_replicant_",
cs.getInstruction()); // insert our call to the rnd fn before the targeted call instruction
/*
* Replace the old integer argument with the randomized one
*/
cs.setArgument(ii, callNewFunc);
}
}
}
}
return true;
}
};
char IntReplacerIterate::ID = 0;
static RegisterPass<IntReplacerIterate> XX("replace-ints-iterate", "Replace int function args with randomizer-integers using instruction iteration");