SeedInfo.cpp

Go to the documentation of this file.
00001 //===-- SeedInfo.cpp ------------------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "Common.h"
00011 
00012 #include "Memory.h"
00013 #include "SeedInfo.h"
00014 #include "TimingSolver.h"
00015 
00016 #include "klee/ExecutionState.h"
00017 #include "klee/Expr.h"
00018 #include "klee/util/ExprUtil.h"
00019 #include "klee/Internal/ADT/KTest.h"
00020 
00021 using namespace klee;
00022 
00023 KTestObject *SeedInfo::getNextInput(const MemoryObject *mo,
00024                                    bool byName) {
00025   if (byName) {
00026     unsigned i;
00027     
00028     for (i=0; i<input->numObjects; ++i) {
00029       KTestObject *obj = &input->objects[i];
00030       if (std::string(obj->name) == mo->name)
00031         if (used.insert(obj).second)
00032           return obj;
00033     }
00034     
00035     // If first unused input matches in size then accept that as
00036     // well.
00037     for (i=0; i<input->numObjects; ++i)
00038       if (!used.count(&input->objects[i]))
00039         break;
00040     if (i<input->numObjects) {
00041       KTestObject *obj = &input->objects[i];
00042       if (obj->numBytes == mo->size) {
00043         used.insert(obj);
00044         klee_warning_once(mo, "using seed input %s[%d] for: %s (no name match)",
00045                           obj->name, obj->numBytes, mo->name.c_str());
00046         return obj;
00047       }
00048     }
00049     
00050     klee_warning_once(mo, "no seed input for: %s", mo->name.c_str());
00051     return 0;
00052   } else {
00053     if (inputPosition >= input->numObjects) {
00054       return 0; 
00055     } else {
00056       return &input->objects[inputPosition++];
00057     }
00058   }
00059 }
00060 
00061 void SeedInfo::patchSeed(const ExecutionState &state, 
00062                          ref<Expr> condition,
00063                          TimingSolver *solver) {
00064   std::vector< ref<Expr> > required(state.constraints.begin(),
00065                                     state.constraints.end());
00066   ExecutionState tmp(required);
00067   tmp.addConstraint(condition);
00068 
00069   // Try and patch direct reads first, this is likely to resolve the
00070   // problem quickly and avoids long traversal of all seed
00071   // values. There are other smart ways to do this, the nicest is if
00072   // we got a minimal counterexample from STP, in which case we would
00073   // just inject those values back into the seed.
00074   std::set< std::pair<const Array*, unsigned> > directReads;
00075   std::vector< ref<ReadExpr> > reads;
00076   findReads(condition, false, reads);
00077   for (std::vector< ref<ReadExpr> >::iterator it = reads.begin(), 
00078          ie = reads.end(); it != ie; ++it) {
00079     ReadExpr *re = it->get();
00080     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(re->index)) {
00081       directReads.insert(std::make_pair(re->updates.root, 
00082                                         (unsigned) CE->getConstantValue()));
00083     }
00084   }
00085   
00086   for (std::set< std::pair<const Array*, unsigned> >::iterator
00087          it = directReads.begin(), ie = directReads.end(); it != ie; ++it) {
00088     const Array *array = it->first;
00089     unsigned i = it->second;
00090     ref<Expr> read = ReadExpr::create(UpdateList(array, true, 0),
00091                                       ConstantExpr::alloc(i, Expr::Int32));
00092     
00093     // If not in bindings then this can't be a violation?
00094     Assignment::bindings_ty::iterator it2 = assignment.bindings.find(array);
00095     if (it2 != assignment.bindings.end()) {
00096       ref<Expr> isSeed = EqExpr::create(read, ConstantExpr::alloc(it2->second[i], Expr::Int8));
00097       bool res;
00098       bool success = solver->mustBeFalse(tmp, isSeed, res);
00099       assert(success && "FIXME: Unhandled solver failure");
00100       (void) success;
00101       if (res) {
00102         ref<ConstantExpr> value;
00103         bool success = solver->getValue(tmp, read, value);
00104         assert(success && "FIXME: Unhandled solver failure");            
00105         (void) success;
00106         it2->second[i] = value->getConstantValue();
00107         tmp.addConstraint(EqExpr::create(read, ConstantExpr::alloc(it2->second[i], Expr::Int8)));
00108       } else {
00109         tmp.addConstraint(isSeed);
00110       }
00111     }
00112   }
00113 
00114   bool res;
00115   bool success = solver->mayBeTrue(state, assignment.evaluate(condition), res);
00116   assert(success && "FIXME: Unhandled solver failure");
00117   (void) success;
00118   if (res)
00119     return;
00120   
00121   // We could still do a lot better than this, for example by looking at
00122   // independence. But really, this shouldn't be happening often.
00123   for (Assignment::bindings_ty::iterator it = assignment.bindings.begin(), 
00124          ie = assignment.bindings.end(); it != ie; ++it) {
00125     const Array *array = it->first;
00126     for (unsigned i=0; i<array->size; ++i) {
00127       ref<Expr> read = ReadExpr::create(UpdateList(array, true, 0),
00128                                         ConstantExpr::alloc(i, Expr::Int32));
00129       ref<Expr> isSeed = EqExpr::create(read, ConstantExpr::alloc(it->second[i], Expr::Int8));
00130       bool res;
00131       bool success = solver->mustBeFalse(tmp, isSeed, res);
00132       assert(success && "FIXME: Unhandled solver failure");
00133       (void) success;
00134       if (res) {
00135         ref<ConstantExpr> value;
00136         bool success = solver->getValue(tmp, read, value);
00137         assert(success && "FIXME: Unhandled solver failure");            
00138         (void) success;
00139         it->second[i] = value->getConstantValue();
00140         tmp.addConstraint(EqExpr::create(read, ConstantExpr::alloc(it->second[i], Expr::Int8)));
00141       } else {
00142         tmp.addConstraint(isSeed);
00143       }
00144     }
00145   }
00146 
00147 #ifndef NDEBUG
00148   {
00149     bool res;
00150     bool success = 
00151       solver->mayBeTrue(state, assignment.evaluate(condition), res);
00152     assert(success && "FIXME: Unhandled solver failure");            
00153     (void) success;
00154     assert(res && "seed patching failed");
00155   }
00156 #endif
00157 }

Generated on Fri Jun 5 03:31:32 2009 for klee by  doxygen 1.5.8