Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}