std::vector<SetOfFormulasPtr> FaultLocalization::allDiagnosis(Formula *TF, std::vector<ProgramTrace*> traces, YicesSolver *yices) { std::vector<SetOfFormulasPtr> MCSes; int progress = 0; int total = traces.size(); // Working formula Formula *WF = new Formula(TF); // For each E in WF, E tagged as soft do unsigned z = 0; std::vector<BoolVarExprPtr> AV; std::map<BoolVarExprPtr, ExprPtr> AVMap; std::vector<ExprPtr> clauses = WF->getExprs(); for(ExprPtr e : clauses) { if (e->isSoft()) { // AI is a new auxiliary var. created std::ostringstream oss; oss << z++; BoolVarExprPtr ai = Expression::mkBoolVar("a_"+oss.str()); ai->setInstruction(e->getInstruction()); ai->setLine(e->getLine()); AV.push_back(ai); AVMap[ai] = e; ExprPtr notai = Expression::mkNot(ai); //notai->setWeight(e->getWeight()); notai->setLine(e->getLine()); notai->setSoft(); WF->add(notai); // Remove E and add EA as hard ExprPtr ea = Expression::mkOr(e, ai); WF->remove(e); ea->setHard(); WF->add(ea); } } if (AV.empty()) { delete WF; std::cout << "No MaxSMT solution!\n"; if (options->verbose()) { std::cout << "==============================================\n"; } return MCSes; } yices->init(); yices->addToContext(WF); for(ProgramTrace *E : traces) { if (options->verbose()) { displayProgressBar(progress, total); } // At this point there is only WF in the context yices->push(); // Assert as hard the error-inducing input formula ExprPtr eiExpr = E->getProgramInputsFormula(TF); eiExpr->setHard(); yices->addToContext(eiExpr); if (options->dbgMsg()) { std::cout << "-- Error-inducing Input: "; eiExpr->dump(); std::cout << std::endl; } // Assert as hard the golden output (if any) // (= return_var golden_output) Value *goldenOutput = E->getExpectedOutput(); if (goldenOutput) { BasicBlock *lastBB = &targetFun->back(); Instruction *lastInst = &lastBB->back(); if (ReturnInst *ret= dyn_cast<ReturnInst>(lastInst)) { Value *retVal = ret->getReturnValue(); if (retVal) { ExprPtr retExpr = Expression::getExprFromValue(retVal); ExprPtr goExpr = Expression::getExprFromValue(goldenOutput); ExprPtr eqExpr = Expression::mkEq(retExpr, goExpr); eqExpr->setHard(); yices->addToContext(eqExpr); if (options->dbgMsg()) { std::cout << "-- Golden ouput: "; eqExpr->dump(); std::cout << std::endl; } } } } // Compute a MCS SetOfFormulasPtr M = allMinMCS(yices, AV, AVMap); if (!M->empty()) { SetOfFormulasPtr M2 = avToClauses(M, AVMap); MCSes.push_back(M2); if (options->printMCS()) { std::cout << "\n" << M2 << "\n" << std::endl; } } else { //if (options->verbose() || options->dbgMsg()) { std::cout << "Empty MCS!\n"; //} } // Backtrack to the point where there // was no Pre/Post-conditions in the formula yices->pop(); // Progress bar progress++; } yices->clean(); delete WF; if (options->verbose()) { displayProgressBar(progress, total); std::cout << std::endl; } return MCSes; }
Formula* EncoderPass::makeTraceFormula() { MSTimer timer1; if(options->printDuration()) { timer1.start(); } // Create an empty trace formula Formula *formula = new Formula(); // Prepare the CFG variables encoder->prepareControlFlow(targetFun); // Pre-process the global variables initGlobalVariables(); // Save the line numbers of the call to assert initAssertCalls(); bool isWeigted = false; unsigned oldLine = 0; Instruction *lastInstruction = NULL; std::vector<ExprPtr> currentConstraits; // Iterate through the function in Topological Order // encode each instructions in SMT constraints // @See: eli.thegreenplace.net/2013/09/16/analyzing-function-cfgs-with-llvm/ ReversePostOrderTraversal<Function*> RPOT(this->targetFun); ReversePostOrderTraversal<Function*>::rpo_iterator itb; for (itb=RPOT.begin(); itb!=RPOT.end(); ++itb) { BasicBlock *bb = *itb; // Propagate pointers when we enter in a new basicblock ExprPtr e = ctx->propagatePointers(bb); if (e) { e->setHard(); formula->add(e); } // HFTF: Encode bug free blocks as hard bool doEncodeBB = true; if (options->htfUsed()) { if(profile->isBugFreeBlock(bb)) { doEncodeBB = false; } } // Iterate through the basicblocks for (BasicBlock::iterator iti=bb->begin(), eti=bb->end(); iti!=eti; ++iti) { Instruction *i = iti; bool doEncodeInst = doEncodeBB; // Check the line number unsigned line = 0; if (MDNode *N = i->getMetadata("dbg")) { DILocation Loc(N); line = Loc.getLineNumber(); // Instruction related to an assert if (ctx->isAssertCall(line)) { isWeigted = false; doEncodeInst = true; } else { // Instruction with line number // (not related to an assert) isWeigted = true; } } else { // Instruction with no line number isWeigted = false; } // Hardened Trace Formula if (options->htfUsed() && !doEncodeInst) { isWeigted = false; } // Encode the instruction in a SMT formula ExprPtr expr = NULL; switch (i->getOpcode()) { case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: case Instruction::FSub: case Instruction::Mul: case Instruction::FMul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::FDiv: case Instruction::URem: case Instruction::SRem: case Instruction::FRem: case Instruction::And: case Instruction::Or: case Instruction::Xor: case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: expr = encoder->encode(cast<BinaryOperator>(i)); break; case Instruction::Select: expr = encoder->encode(cast<SelectInst>(i)); break; case Instruction::PHI: expr = encoder->encode(cast<PHINode>(i)); isWeigted = false; break; case Instruction::Br: expr = encoder->encode(cast<BranchInst>(i), loops); isWeigted = false; break; case Instruction::Switch: expr = encoder->encode(cast<SwitchInst>(i)); break; case Instruction::ICmp: expr = encoder->encode(cast<ICmpInst>(i)); break; case Instruction::Call: expr = encoder->encode(cast<CallInst>(i), preCond, postCond); if (!expr) { // Do not encode sniper_x functions. continue; } isWeigted = false; break; case Instruction::Alloca: expr = encoder->encode(cast<AllocaInst>(i)); if (!expr) { continue; } isWeigted = false; break; case Instruction::Store: expr = encoder->encode(cast<StoreInst>(i)); break; case Instruction::Load: expr = encoder->encode(cast<LoadInst>(i), postCond); break; case Instruction::GetElementPtr: expr = encoder->encode(cast<GetElementPtrInst>(i)); isWeigted = false; break; case Instruction::SExt: expr = encoder->encode(cast<SExtInst>(i)); isWeigted = false; break; case Instruction::ZExt: expr = encoder->encode(cast<ZExtInst>(i)); isWeigted = false; break; case Instruction::Ret: expr = encoder->encode(cast<ReturnInst>(i)); isWeigted = false; break; case Instruction::Unreachable: // Do not encode. continue; case Instruction::PtrToInt: { // Instruction added by SNIPER std::string instName = i->getName().str(); std::string prefix("sniper_ptrVal"); if (!instName.compare(0, prefix.size(), prefix)) { continue; } // NO BREAK! } case Instruction::VAArg: case Instruction::Invoke: case Instruction::Trunc: case Instruction::FPTrunc: case Instruction::FPExt: case Instruction::UIToFP: case Instruction::SIToFP: case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::IntToPtr: case Instruction::BitCast: case Instruction::FCmp: case Instruction::ExtractElement: case Instruction::InsertElement: case Instruction::ShuffleVector: case Instruction::ExtractValue: case Instruction::InsertValue: i->dump(); assert("unsupported LLVM instruction!\n"); break; default: llvm_unreachable("Illegal opcode!"); } assert(expr && "Expression is null!"); // Atoi checking if (isAtoiFunction(i)) { isWeigted = false; } // Instruction with line number if (isWeigted) { // Add each instruction separately if (options->instructionGranularityLevel()) { expr->setInstruction(i); expr->setSoft(); formula->add(expr); } // Pack and add all instructions from // the same line number else if (options->lineGranularityLevel()) { assert(line>0 && "Illegal line number!"); // New line, Add the collect constraints to the formula if (line!=oldLine && oldLine!=0) { assert(!currentConstraits.empty() && "No constraints!"); assert(lastInstruction && "Instruction is null!"); ExprPtr e = Expression::mkAnd(currentConstraits); e->setInstruction(lastInstruction); e->setSoft(); formula->add(e); currentConstraits.clear(); } currentConstraits.push_back(expr); oldLine = line; lastInstruction = i; } // Block level else if (options->blockGranularityLevel()) { currentConstraits.push_back(expr); } else { assert("Unknow granularity level!"); } } // Instruction with no line number else { expr->setHard(); formula->add(expr); } } // End of basic block iteration if (options->blockGranularityLevel()) { if (!currentConstraits.empty()) { ExprPtr e = Expression::mkAnd(currentConstraits); e->setInstruction(lastInstruction); e->setSoft(); formula->add(e); currentConstraits.clear(); } } } // Add the remaining soft constraints to the formula if (!currentConstraits.empty()) { assert(options->lineGranularityLevel() && "Some instructions could not be encoded!"); assert(lastInstruction && "Instruction is null!"); ExprPtr e = Expression::mkAnd(currentConstraits); e->setInstruction(lastInstruction); e->setSoft(); formula->add(e); currentConstraits.clear(); } if(options->printDuration()) { timer1.stop("Trace Formula Encoding Time"); } return formula; }