Skip to content

Commit

Permalink
disable Alive added, random mutate added
Browse files Browse the repository at this point in the history
  • Loading branch information
spica authored and spica committed Nov 8, 2023
1 parent da629d4 commit ed3f224
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 126 deletions.
69 changes: 54 additions & 15 deletions tools/alive-mutate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,26 @@ llvm::cl::opt<bool> removeUndef(
llvm::cl::desc("remove all undef in all functions in the input module"),
llvm::cl::cat(mutatorArgs));

llvm::cl::opt<bool> masterRNG(
LLVM_ARGS_PREFIX "masterRNG",
llvm::cl::value_desc("turn on master RNG mode"),
llvm::cl::desc("master RNG will generate a list of random seeds and set use"
" one seed for every mutant"),
llvm::cl::cat(mutatorArgs));

llvm::cl::opt<bool> randomMutate(
LLVM_ARGS_PREFIX "randomMutate",
llvm::cl::value_desc("turn on randomMutate mode"),
llvm::cl::desc("Random mutate mode will random mutate an instruction in the"
" function instead of linear sequence"),
llvm::cl::cat(mutatorArgs));

llvm::cl::opt<bool> disableAlive(
LLVM_ARGS_PREFIX "disableAlive",
llvm::cl::value_desc("a flag to disable alive2 verifications"),
llvm::cl::desc("don't verify mutated result by alive2"),
llvm::cl::cat(mutatorArgs), llvm::cl::init(false));

llvm::cl::opt<bool> verbose(LLVM_ARGS_PREFIX "v",
llvm::cl::value_desc("verbose mode"),
llvm::cl::desc("specify if verbose mode is on"),
Expand Down Expand Up @@ -131,6 +151,7 @@ llvm::cl::list<size_t>
llvm::cl::CommaSeparated, llvm::cl::cat(mutatorArgs));


std::vector<unsigned> RNGseeds;
unique_ptr<Cache> cache;
std::stringstream logStream;
// To eliminate extra verifier construction;
Expand Down Expand Up @@ -214,8 +235,16 @@ see alive-tv --version for LLVM version info,
if (outputFolder.back() != '/')
outputFolder += '/';


if (randomSeed >= 0) {
Random::setSeed((unsigned)randomSeed);
if(masterRNG){
assert(numCopy > 0 && "master RNG setting should only be allowed under copy mode!\n");
RNGseeds.resize(numCopy);
for(int i=0;i<numCopy;++i){
RNGseeds[i]=Random::getRandomUnsigned();
}
}
}

if (numCopy < 0 && timeElapsed < 0) {
Expand Down Expand Up @@ -333,17 +362,23 @@ bool verifyInput(std::shared_ptr<llvm::Module>& M1){
}

void copyMode(std::shared_ptr<llvm::Module>& pm){
if (copyFunctions != 0) {
if (copyFunctions != 0) {
mutator_util::propagateFunctionsInModule(pm.get(), copyFunctions);
}
std::unique_ptr<Mutator> mutator = std::make_unique<ModuleMutator>(
pm, invalidFunctions, verbose, onEveryFunction);
pm, invalidFunctions, verbose, onEveryFunction, randomMutate);
if (bool init = mutator->init(); init) {

//Eliminate the influence of verifyInput
if(!masterRNG && randomSeed >= 0){
Random::setSeed((unsigned)randomSeed);
}
for (int i = 0; i < numCopy; ++i) {
if (verbose) {
std::cout << "Running " << i << "th copies." << std::endl;
}
if(masterRNG){
Random::setSeed(RNGseeds[i]);
}
runOnce(i, *mutator);


Expand All @@ -359,7 +394,7 @@ void timeMode(std::shared_ptr<llvm::Module>& pm){
mutator_util::propagateFunctionsInModule(pm.get(), copyFunctions);
}
std::unique_ptr<Mutator> mutator = std::make_unique<ModuleMutator>(
pm, invalidFunctions, verbose, onEveryFunction);
pm, invalidFunctions, verbose, onEveryFunction, randomMutate);
bool init = mutator->init();
if (!init) {
cerr << "Cannot find any location to mutate, " + inputFile + " skipped\n";
Expand Down Expand Up @@ -387,16 +422,18 @@ void runOnce(int ith, Mutator &mutator){

auto M1 = mutator.getModule();

if(!verifier.has_value()){
llvm::Triple targetTriple(M1.get()->getTargetTriple());
initVerifier(targetTriple);
if(!disableAlive) {
if (!verifier.has_value()) {
llvm::Triple targetTriple(M1.get()->getTargetTriple());
initVerifier(targetTriple);
}
}


const string optFunc = mutator.getCurrentFunction();
bool shouldLog=false;

if (llvm::Function *pf1 = M1->getFunction(optFunc); pf1 != nullptr) {
if (llvm::Function *pf1 = M1->getFunction(optFunc); !disableAlive && pf1 != nullptr) {
if (!pf1->isDeclaration()) {
std::unique_ptr<llvm::Module> M2 = llvm::CloneModule(*M1);
llvm_util::optimize_module(M2.get(), optPass);
Expand All @@ -409,13 +446,15 @@ void runOnce(int ith, Mutator &mutator){
}
}

if(shouldLog){
if(shouldLog || disableAlive){
mutator.saveModule(getOutputSrcFilename(ith));
std::ofstream logFile(getOutputLogFilename(ith));
assert(logFile.is_open());
logFile<<"Current seed: "<<Random::getSeed()<<"\n";
logFile << "Source file:" << M1->getSourceFileName() << "\n";
logFile<<logStream.rdbuf();
logStream.str("");
if(!disableAlive){
std::ofstream logFile(getOutputLogFilename(ith));
assert(logFile.is_open());
logFile<<"Current seed: "<<Random::getSeed()<<"\n";
logFile << "Source file:" << M1->getSourceFileName() << "\n";
logFile<<logStream.rdbuf();
logStream.str("");
}
}
}
134 changes: 87 additions & 47 deletions tools/mutator-utils/mutator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,18 @@ void FunctionMutator::resetIterator() {
initAtFunctionEntry();
}

void FunctionMutator::resetRandomIterator(){
bit=currentFunction->begin();
for(size_t i=Random::getRandomUnsigned()%currentFunction->size();i;--i,++bit);
iit=bit->begin();
for(size_t i=Random::getRandomUnsigned()%bit->size();i;--i,++iit);
initAtNewBasicBlock();
initAtFunctionEntry();
moveToNextMutant();
bitInTmp=((llvm::BasicBlock*)&*vMap[&*bit])->getIterator();
iitInTmp=((llvm::Instruction*)&*vMap[&*iit])->getIterator();
}

bool FunctionMutator::canMutate(const llvm::Instruction &inst,
const llvm::StringSet<> &filterSet) {
// contain immarg attributes
Expand Down Expand Up @@ -319,8 +331,6 @@ void FunctionMutator::mutate() {
}

void FunctionMutator::moveToNextInstruction() {
assert(domVals.inBackup());
domVals.push_back(&*iit);
++iit;
if (iit == bit->end()) {
moveToNextBasicBlock();
Expand Down Expand Up @@ -353,42 +363,18 @@ void FunctionMutator::moveToNextBasicBlock() {
} else {
iit = bit->begin();
}
calcDomVals();
}

void FunctionMutator::moveToNextMutant() {
moveToNextInstruction();
while (!canMutate(*iit, filterSet))
moveToNextInstruction();
domVals.restoreBackup();
initAtNewInstruction();
}

void FunctionMutator::calcDomVals() {
domVals.deleteBackup();
domVals.resize(currentFunction->arg_size());
// add BasicBlocks before bitTmp
for (auto bitTmp = currentFunction->begin(); bitTmp != bit; ++bitTmp) {
if (DT.dominates(&*bitTmp, &*bit)) {
for (auto iitTmp = bitTmp->begin(); iitTmp != bitTmp->end(); ++iitTmp) {
//Some special inst like unwind invoke would be false here
if(DT.dominates(&*iitTmp, &*iit)){
domVals.push_back(&*iitTmp);
}
}
}
}
domVals.startBackup();
// add Instructions before iitTmp
for (auto iitTmp = bit->begin(); iitTmp != iit; ++iitTmp) {
if (DT.dominates(&*iitTmp, &*iit)) {
domVals.push_back(&*iitTmp);
}
}
}

void FunctionMutator::resetTmpCopy(std::shared_ptr<llvm::Module> copy) {
extraValues.clear();
invalidValues.clear();
tmpFuncs.clear();
tmpCopy = copy;
assert(vMap.find(currentFunction) != vMap.end() &&
Expand Down Expand Up @@ -444,12 +430,19 @@ void FunctionMutator::addFunctionArguments(
void FunctionMutator::fixAllValues(llvm::SmallVector<llvm::Value *> &vals) {
if (!lazyUpdateInsts.empty()) {
llvm::ValueToValueMapTy VMap;
llvm::DenseSet<llvm::Instruction*> newInvalidValues;
addFunctionArguments(lazyUpdateArgTys, VMap);
for (size_t i = 0; i < extraValues.size(); ++i) {
if (VMap.find(extraValues[i]) != VMap.end()) {
extraValues[i] = (llvm::Value *)&*VMap[extraValues[i]];
}
}
for(auto it=invalidValues.begin();it!=invalidValues.end();++it){
if(VMap.find(*it)!=VMap.end()){
newInvalidValues.insert((llvm::Instruction*)&*VMap[*it]);
}
}
invalidValues=std::move(newInvalidValues);
for (size_t i = 0; i < vals.size(); ++i) {
vals[i] = (llvm::Value *)&*VMap[vals[i]];
}
Expand All @@ -471,23 +464,57 @@ llvm::Value *FunctionMutator::getRandomConstant(llvm::Type *ty) {
return llvm::UndefValue::get(ty);
}

llvm::Value *FunctionMutator::getRandomDominatedValue(llvm::Type *ty) {
if (ty != nullptr && !domVals.empty()) {
llvm::Value *FunctionMutator::getRandomDominatedInstruction(llvm::Type *ty) {
if(ty!=nullptr){
auto bbIt=currentFunction->begin();
auto instIt=iit;
bool isIntTy = ty->isIntegerTy();
for (size_t i = 0, pos = Random::getRandomUnsigned() % domVals.size();
i < domVals.size(); ++i, ++pos) {
if (pos == domVals.size())
pos = 0;
if (domVals[pos]->getType() == ty) {
return &*vMap[domVals[pos]];
} else if (isIntTy && domVals[pos]->getType()->isIntegerTy()) {
llvm::Value *valInTmp = &*vMap[domVals[pos]];
llvm::Instruction *insertBefore = nullptr;
if (llvm::isa<llvm::Argument>(valInTmp)) {
insertBefore = &*functionInTmp->begin()->begin();
} else {
insertBefore = &*iitInTmp;
for(size_t pos=Random::getRandomUnsigned()%currentFunction->size();pos;--pos,++bbIt);
for(size_t i=0;i<currentFunction->size();++i,++bbIt){
if(bbIt==currentFunction->end()){
bbIt=currentFunction->begin();
}
if(DT.dominates(&*bbIt, &*bit) || bbIt==bit){
instIt=bbIt->begin();
for(size_t pos=Random::getRandomUnsigned()%bbIt->size();pos;--pos,++instIt);
for(size_t inner_i=0;inner_i<bbIt->size();++inner_i,++instIt){
if(instIt==bbIt->end()){
instIt=bbIt->begin();
}
if(invalidValues.contains((llvm::Instruction*)&*vMap[&*instIt])){
continue;
}
if(DT.dominates(&*instIt, &*iit)){
if(instIt->getType()==ty){
return &*vMap[&*instIt];
}else if(isIntTy && instIt->getType()->isIntegerTy()){
llvm::Value *valInTmp = &*vMap[&*instIt];
llvm::Instruction *insertBefore = &*iitInTmp;
return mutator_util::updateIntegerSize(
valInTmp, (llvm::IntegerType *)ty, &*insertBefore);
}
}
}
}
}
}
return nullptr;
}

llvm::Value *FunctionMutator::getRandomArgument(llvm::Type *ty) {
if(currentFunction->arg_size()!=0){
bool isIntTy = ty->isIntegerTy();
for(size_t i=0,pos=Random::getRandomUnsigned()%currentFunction->arg_size();
i<currentFunction->arg_size();++i,++pos){
if(pos==currentFunction->arg_size()){
pos=0;
}
llvm::Argument* curArg=currentFunction->getArg(pos);
if(currentFunction->getArg(pos)->getType()==ty){
return &*vMap[curArg];
}else if (isIntTy && curArg->getType()->isIntegerTy()) {
llvm::Instruction *insertBefore = &*functionInTmp->begin()->begin();
llvm::Value *valInTmp = &*vMap[curArg];
return mutator_util::updateIntegerSize(
valInTmp, (llvm::IntegerType *)ty, &*insertBefore);
}
Expand All @@ -498,10 +525,18 @@ llvm::Value *FunctionMutator::getRandomDominatedValue(llvm::Type *ty) {

llvm::Value *FunctionMutator::getRandomValueFromExtraValue(llvm::Type *ty) {
if (ty != nullptr && !extraValues.empty()) {
return mutator_util::findRandomInArray<llvm::Value *, llvm::Type *>(
extraValues, ty,
[](llvm::Value *v, llvm::Type *ty) { return v->getType() == ty; },
nullptr);
for(size_t i=0,pos=Random::getRandomUnsigned()%extraValues.size();i<extraValues.size();++i,++pos){
if(pos==extraValues.size()){
pos=0;
}
if(llvm::Instruction* inst=llvm::dyn_cast<llvm::Instruction>(extraValues[pos]); inst){
if(!invalidValues.contains(inst) && inst->getType()==ty){
return extraValues[pos];
}
}else if(extraValues[pos]->getType()==ty){
return extraValues[pos];
}
}
}
return nullptr;
}
Expand Down Expand Up @@ -566,7 +601,6 @@ static bool hasUndefOperand(llvm::Instruction *inst) {

void FunctionMutator::removeAllUndef() {
resetIterator();
calcDomVals();
llvm::SmallVector<llvm::Value *> vec;
for (auto it = inst_begin(functionInTmp); it != inst_end(functionInTmp);
++it) {
Expand Down Expand Up @@ -654,6 +688,10 @@ void ModuleMutator::mutateModule(const std::string &outputFileName) {
functionMutants[i]->removeTmpFunction();
}
} else {
if(randomMutate){
curFunction = Random::getRandomUnsigned() % functionMutants.size();
functionMutants[curFunction]->resetRandomIterator();
}
functionMutants[curFunction]->mutate();
curFunctionName =
functionMutants[curFunction]->getCurrentFunction()->getName();
Expand All @@ -669,6 +707,8 @@ void ModuleMutator::mutateModule(const std::string &outputFileName) {
void ModuleMutator::saveModule(const std::string &outputFileName) {
std::error_code ec;
llvm::raw_fd_ostream fout(outputFileName, ec);
fout<<";"<<curFunctionName<<"\n";
fout<<";current seed:" << Random::getSeed()<<"\n";
fout << *tmpCopy;
fout.close();
if (debug) {
Expand Down
Loading

0 comments on commit ed3f224

Please sign in to comment.