00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Common.h"
00011
00012 #include "Searcher.h"
00013
00014 #include "CoreStats.h"
00015 #include "Executor.h"
00016 #include "PTree.h"
00017 #include "StatsTracker.h"
00018
00019 #include "klee/ExecutionState.h"
00020 #include "klee/Statistics.h"
00021 #include "klee/Internal/Module/InstructionInfoTable.h"
00022 #include "klee/Internal/Module/KInstruction.h"
00023 #include "klee/Internal/Module/KModule.h"
00024 #include "klee/Internal/ADT/DiscretePDF.h"
00025 #include "klee/Internal/ADT/RNG.h"
00026 #include "klee/Internal/Support/ModuleUtil.h"
00027 #include "klee/Internal/System/Time.h"
00028
00029 #include "llvm/Constants.h"
00030 #include "llvm/Instructions.h"
00031 #include "llvm/Module.h"
00032 #include "llvm/Support/CallSite.h"
00033 #include "llvm/Support/CFG.h"
00034 #include "llvm/Support/CommandLine.h"
00035
00036 #include <cassert>
00037 #include <fstream>
00038 #include <climits>
00039
00040 using namespace klee;
00041 using namespace llvm;
00042
00043 namespace {
00044 cl::opt<bool>
00045 DebugLogMerge("debug-log-merge");
00046 }
00047
00048 namespace klee {
00049 extern RNG theRNG;
00050 }
00051
00052 Searcher::~Searcher() {
00053 }
00054
00056
00057 ExecutionState &DFSSearcher::selectState() {
00058 return *states.back();
00059 }
00060
00061 void DFSSearcher::update(ExecutionState *current,
00062 const std::set<ExecutionState*> &addedStates,
00063 const std::set<ExecutionState*> &removedStates) {
00064 states.insert(states.end(),
00065 addedStates.begin(),
00066 addedStates.end());
00067 for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
00068 ie = removedStates.end(); it != ie; ++it) {
00069 ExecutionState *es = *it;
00070 if (es == states.back()) {
00071 states.pop_back();
00072 } else {
00073 bool ok = false;
00074
00075 for (std::vector<ExecutionState*>::iterator it = states.begin(),
00076 ie = states.end(); it != ie; ++it) {
00077 if (es==*it) {
00078 states.erase(it);
00079 ok = true;
00080 break;
00081 }
00082 }
00083
00084 assert(ok && "invalid state removed");
00085 }
00086 }
00087 }
00088
00090
00091 ExecutionState &RandomSearcher::selectState() {
00092 return *states[theRNG.getInt32()%states.size()];
00093 }
00094
00095 void RandomSearcher::update(ExecutionState *current,
00096 const std::set<ExecutionState*> &addedStates,
00097 const std::set<ExecutionState*> &removedStates) {
00098 states.insert(states.end(),
00099 addedStates.begin(),
00100 addedStates.end());
00101 for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
00102 ie = removedStates.end(); it != ie; ++it) {
00103 ExecutionState *es = *it;
00104 bool ok = false;
00105
00106 for (std::vector<ExecutionState*>::iterator it = states.begin(),
00107 ie = states.end(); it != ie; ++it) {
00108 if (es==*it) {
00109 states.erase(it);
00110 ok = true;
00111 break;
00112 }
00113 }
00114
00115 assert(ok && "invalid state removed");
00116 }
00117 }
00118
00120
00121 WeightedRandomSearcher::WeightedRandomSearcher(Executor &_executor,
00122 WeightType _type)
00123 : executor(_executor),
00124 states(new DiscretePDF<ExecutionState*>()),
00125 type(_type) {
00126 switch(type) {
00127 case Depth:
00128 updateWeights = false;
00129 break;
00130 case InstCount:
00131 case CPInstCount:
00132 case QueryCost:
00133 case MinDistToUncovered:
00134 case CoveringNew:
00135 updateWeights = true;
00136 break;
00137 default:
00138 assert(0 && "invalid weight type");
00139 }
00140 }
00141
00142 WeightedRandomSearcher::~WeightedRandomSearcher() {
00143 delete states;
00144 }
00145
00146 ExecutionState &WeightedRandomSearcher::selectState() {
00147 return *states->choose(theRNG.getDoubleL());
00148 }
00149
00150 double WeightedRandomSearcher::getWeight(ExecutionState *es) {
00151 switch(type) {
00152 default:
00153 case Depth:
00154 return es->weight;
00155 case InstCount: {
00156 uint64_t count = theStatisticManager->getIndexedValue(stats::instructions,
00157 es->pc->info->id);
00158 double inv = 1. / std::max((uint64_t) 1, count);
00159 return inv * inv;
00160 }
00161 case CPInstCount: {
00162 StackFrame &sf = es->stack.back();
00163 uint64_t count = sf.callPathNode->statistics.getValue(stats::instructions);
00164 double inv = 1. / std::max((uint64_t) 1, count);
00165 return inv;
00166 }
00167 case QueryCost:
00168 return (es->queryCost < .1) ? 1. : 1./es->queryCost;
00169 case CoveringNew:
00170 case MinDistToUncovered: {
00171 uint64_t md2u = computeMinDistToUncovered(es->pc,
00172 es->stack.back().minDistToUncoveredOnReturn);
00173
00174 double invMD2U = 1. / (md2u ? md2u : 10000);
00175 if (type==CoveringNew) {
00176 double invCovNew = 0.;
00177 if (es->instsSinceCovNew)
00178 invCovNew = 1. / std::max(1, (int) es->instsSinceCovNew - 1000);
00179 return (invCovNew * invCovNew + invMD2U * invMD2U);
00180 } else {
00181 return invMD2U * invMD2U;
00182 }
00183 }
00184 }
00185 }
00186
00187 void WeightedRandomSearcher::update(ExecutionState *current,
00188 const std::set<ExecutionState*> &addedStates,
00189 const std::set<ExecutionState*> &removedStates) {
00190 if (current && updateWeights && !removedStates.count(current))
00191 states->update(current, getWeight(current));
00192
00193 for (std::set<ExecutionState*>::const_iterator it = addedStates.begin(),
00194 ie = addedStates.end(); it != ie; ++it) {
00195 ExecutionState *es = *it;
00196 states->insert(es, getWeight(es));
00197 }
00198
00199 for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
00200 ie = removedStates.end(); it != ie; ++it) {
00201 states->remove(*it);
00202 }
00203 }
00204
00205 bool WeightedRandomSearcher::empty() {
00206 return states->empty();
00207 }
00208
00210
00211 RandomPathSearcher::RandomPathSearcher(Executor &_executor)
00212 : executor(_executor) {
00213 }
00214
00215 RandomPathSearcher::~RandomPathSearcher() {
00216 }
00217
00218 ExecutionState &RandomPathSearcher::selectState() {
00219 unsigned flips=0, bits=0;
00220 PTree::Node *n = executor.processTree->root;
00221
00222 while (!n->data) {
00223 if (!n->left) {
00224 n = n->right;
00225 } else if (!n->right) {
00226 n = n->left;
00227 } else {
00228 if (bits==0) {
00229 flips = theRNG.getInt32();
00230 bits = 32;
00231 }
00232 --bits;
00233 n = (flips&(1<<bits)) ? n->left : n->right;
00234 }
00235 }
00236
00237 return *n->data;
00238 }
00239
00240 void RandomPathSearcher::update(ExecutionState *current,
00241 const std::set<ExecutionState*> &addedStates,
00242 const std::set<ExecutionState*> &removedStates) {
00243 }
00244
00245 bool RandomPathSearcher::empty() {
00246 return executor.states.empty();
00247 }
00248
00250
00251 BumpMergingSearcher::BumpMergingSearcher(Executor &_executor, Searcher *_baseSearcher)
00252 : executor(_executor),
00253 baseSearcher(_baseSearcher),
00254 mergeFunction(executor.kmodule->kleeMergeFn) {
00255 }
00256
00257 BumpMergingSearcher::~BumpMergingSearcher() {
00258 delete baseSearcher;
00259 }
00260
00262
00263 Instruction *BumpMergingSearcher::getMergePoint(ExecutionState &es) {
00264 if (mergeFunction) {
00265 Instruction *i = es.pc->inst;
00266
00267 if (i->getOpcode()==Instruction::Call) {
00268 CallSite cs(cast<CallInst>(i));
00269 if (mergeFunction==cs.getCalledFunction())
00270 return i;
00271 }
00272 }
00273
00274 return 0;
00275 }
00276
00277 ExecutionState &BumpMergingSearcher::selectState() {
00278 entry:
00279
00280 if (baseSearcher->empty()) {
00281 std::map<llvm::Instruction*, ExecutionState*>::iterator it =
00282 statesAtMerge.begin();
00283 ExecutionState *es = it->second;
00284 statesAtMerge.erase(it);
00285 ++es->pc;
00286
00287 baseSearcher->addState(es);
00288 }
00289
00290 ExecutionState &es = baseSearcher->selectState();
00291
00292 if (Instruction *mp = getMergePoint(es)) {
00293 std::map<llvm::Instruction*, ExecutionState*>::iterator it =
00294 statesAtMerge.find(mp);
00295
00296 baseSearcher->removeState(&es);
00297
00298 if (it==statesAtMerge.end()) {
00299 statesAtMerge.insert(std::make_pair(mp, &es));
00300 } else {
00301 ExecutionState *mergeWith = it->second;
00302 if (mergeWith->merge(es)) {
00303
00304
00305 baseSearcher->addState(&es);
00306 executor.terminateState(es);
00307 } else {
00308 it->second = &es;
00309 ++mergeWith->pc;
00310
00311 baseSearcher->addState(mergeWith);
00312 }
00313 }
00314
00315 goto entry;
00316 } else {
00317 return es;
00318 }
00319 }
00320
00321 void BumpMergingSearcher::update(ExecutionState *current,
00322 const std::set<ExecutionState*> &addedStates,
00323 const std::set<ExecutionState*> &removedStates) {
00324 baseSearcher->update(current, addedStates, removedStates);
00325 }
00326
00328
00329 MergingSearcher::MergingSearcher(Executor &_executor, Searcher *_baseSearcher)
00330 : executor(_executor),
00331 baseSearcher(_baseSearcher),
00332 mergeFunction(executor.kmodule->kleeMergeFn) {
00333 }
00334
00335 MergingSearcher::~MergingSearcher() {
00336 delete baseSearcher;
00337 }
00338
00340
00341 Instruction *MergingSearcher::getMergePoint(ExecutionState &es) {
00342 if (mergeFunction) {
00343 Instruction *i = es.pc->inst;
00344
00345 if (i->getOpcode()==Instruction::Call) {
00346 CallSite cs(cast<CallInst>(i));
00347 if (mergeFunction==cs.getCalledFunction())
00348 return i;
00349 }
00350 }
00351
00352 return 0;
00353 }
00354
00355 ExecutionState &MergingSearcher::selectState() {
00356 while (!baseSearcher->empty()) {
00357 ExecutionState &es = baseSearcher->selectState();
00358 if (getMergePoint(es)) {
00359 baseSearcher->removeState(&es, &es);
00360 statesAtMerge.insert(&es);
00361 } else {
00362 return es;
00363 }
00364 }
00365
00366
00367 std::map<Instruction*, std::vector<ExecutionState*> > merges;
00368 for (std::set<ExecutionState*>::const_iterator it = statesAtMerge.begin(),
00369 ie = statesAtMerge.end(); it != ie; ++it) {
00370 ExecutionState &state = **it;
00371 Instruction *mp = getMergePoint(state);
00372
00373 merges[mp].push_back(&state);
00374 }
00375
00376 if (DebugLogMerge)
00377 llvm::cerr << "-- all at merge --\n";
00378 for (std::map<Instruction*, std::vector<ExecutionState*> >::iterator
00379 it = merges.begin(), ie = merges.end(); it != ie; ++it) {
00380 if (DebugLogMerge) {
00381 llvm::cerr << "\tmerge: " << it->first << " [";
00382 for (std::vector<ExecutionState*>::iterator it2 = it->second.begin(),
00383 ie2 = it->second.end(); it2 != ie2; ++it2) {
00384 ExecutionState *state = *it2;
00385 llvm::cerr << state << ", ";
00386 }
00387 llvm::cerr << "]\n";
00388 }
00389
00390
00391 std::set<ExecutionState*> toMerge(it->second.begin(), it->second.end());
00392 while (!toMerge.empty()) {
00393 ExecutionState *base = *toMerge.begin();
00394 toMerge.erase(toMerge.begin());
00395
00396 std::set<ExecutionState*> toErase;
00397 for (std::set<ExecutionState*>::iterator it = toMerge.begin(),
00398 ie = toMerge.end(); it != ie; ++it) {
00399 ExecutionState *mergeWith = *it;
00400
00401 if (base->merge(*mergeWith)) {
00402 toErase.insert(mergeWith);
00403 }
00404 }
00405 if (DebugLogMerge && !toErase.empty()) {
00406 llvm::cerr << "\t\tmerged: " << base << " with [";
00407 for (std::set<ExecutionState*>::iterator it = toErase.begin(),
00408 ie = toErase.end(); it != ie; ++it) {
00409 if (it!=toErase.begin()) llvm::cerr << ", ";
00410 llvm::cerr << *it;
00411 }
00412 llvm::cerr << "]\n";
00413 }
00414 for (std::set<ExecutionState*>::iterator it = toErase.begin(),
00415 ie = toErase.end(); it != ie; ++it) {
00416 std::set<ExecutionState*>::iterator it2 = toMerge.find(*it);
00417 assert(it2!=toMerge.end());
00418 executor.terminateState(**it);
00419 toMerge.erase(it2);
00420 }
00421
00422
00423 statesAtMerge.erase(statesAtMerge.find(base));
00424 ++base->pc;
00425 baseSearcher->addState(base);
00426 }
00427 }
00428
00429 if (DebugLogMerge)
00430 llvm::cerr << "-- merge complete, continuing --\n";
00431
00432 return selectState();
00433 }
00434
00435 void MergingSearcher::update(ExecutionState *current,
00436 const std::set<ExecutionState*> &addedStates,
00437 const std::set<ExecutionState*> &removedStates) {
00438 if (!removedStates.empty()) {
00439 std::set<ExecutionState *> alt = removedStates;
00440 for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
00441 ie = removedStates.end(); it != ie; ++it) {
00442 ExecutionState *es = *it;
00443 std::set<ExecutionState*>::const_iterator it = statesAtMerge.find(es);
00444 if (it!=statesAtMerge.end()) {
00445 statesAtMerge.erase(it);
00446 alt.erase(alt.find(es));
00447 }
00448 }
00449 baseSearcher->update(current, addedStates, alt);
00450 } else {
00451 baseSearcher->update(current, addedStates, removedStates);
00452 }
00453 }
00454
00456
00457 BatchingSearcher::BatchingSearcher(Searcher *_baseSearcher,
00458 double _timeBudget,
00459 unsigned _instructionBudget)
00460 : baseSearcher(_baseSearcher),
00461 timeBudget(_timeBudget),
00462 instructionBudget(_instructionBudget),
00463 lastState(0) {
00464
00465 }
00466
00467 BatchingSearcher::~BatchingSearcher() {
00468 delete baseSearcher;
00469 }
00470
00471 ExecutionState &BatchingSearcher::selectState() {
00472 if (!lastState ||
00473 (util::getWallTime()-lastStartTime)>timeBudget ||
00474 (stats::instructions-lastStartInstructions)>instructionBudget) {
00475 if (lastState) {
00476 double delta = util::getWallTime()-lastStartTime;
00477 if (delta>timeBudget*1.1) {
00478 llvm::cerr << "KLEE: increased time budget from " << timeBudget << " to " << delta << "\n";
00479 timeBudget = delta;
00480 }
00481 }
00482 lastState = &baseSearcher->selectState();
00483 lastStartTime = util::getWallTime();
00484 lastStartInstructions = stats::instructions;
00485 return *lastState;
00486 } else {
00487 return *lastState;
00488 }
00489 }
00490
00491 void BatchingSearcher::update(ExecutionState *current,
00492 const std::set<ExecutionState*> &addedStates,
00493 const std::set<ExecutionState*> &removedStates) {
00494 if (removedStates.count(lastState))
00495 lastState = 0;
00496 baseSearcher->update(current, addedStates, removedStates);
00497 }
00498
00499
00500
00501 IterativeDeepeningTimeSearcher::IterativeDeepeningTimeSearcher(Searcher *_baseSearcher)
00502 : baseSearcher(_baseSearcher),
00503 time(1.) {
00504 }
00505
00506 IterativeDeepeningTimeSearcher::~IterativeDeepeningTimeSearcher() {
00507 delete baseSearcher;
00508 }
00509
00510 ExecutionState &IterativeDeepeningTimeSearcher::selectState() {
00511 ExecutionState &res = baseSearcher->selectState();
00512 startTime = util::getWallTime();
00513 return res;
00514 }
00515
00516 void IterativeDeepeningTimeSearcher::update(ExecutionState *current,
00517 const std::set<ExecutionState*> &addedStates,
00518 const std::set<ExecutionState*> &removedStates) {
00519 double elapsed = util::getWallTime() - startTime;
00520
00521 if (!removedStates.empty()) {
00522 std::set<ExecutionState *> alt = removedStates;
00523 for (std::set<ExecutionState*>::const_iterator it = removedStates.begin(),
00524 ie = removedStates.end(); it != ie; ++it) {
00525 ExecutionState *es = *it;
00526 std::set<ExecutionState*>::const_iterator it = pausedStates.find(es);
00527 if (it!=pausedStates.end()) {
00528 pausedStates.erase(it);
00529 alt.erase(alt.find(es));
00530 }
00531 }
00532 baseSearcher->update(current, addedStates, alt);
00533 } else {
00534 baseSearcher->update(current, addedStates, removedStates);
00535 }
00536
00537 if (current && !removedStates.count(current) && elapsed>time) {
00538 pausedStates.insert(current);
00539 baseSearcher->removeState(current);
00540 }
00541
00542 if (baseSearcher->empty()) {
00543 time *= 2;
00544 llvm::cerr << "KLEE: increasing time budget to: " << time << "\n";
00545 baseSearcher->update(0, pausedStates, std::set<ExecutionState*>());
00546 pausedStates.clear();
00547 }
00548 }
00549
00550
00551
00552 InterleavedSearcher::InterleavedSearcher(const std::vector<Searcher*> &_searchers)
00553 : searchers(_searchers),
00554 index(1) {
00555 }
00556
00557 InterleavedSearcher::~InterleavedSearcher() {
00558 for (std::vector<Searcher*>::const_iterator it = searchers.begin(),
00559 ie = searchers.end(); it != ie; ++it)
00560 delete *it;
00561 }
00562
00563 ExecutionState &InterleavedSearcher::selectState() {
00564 Searcher *s = searchers[--index];
00565 if (index==0) index = searchers.size();
00566 return s->selectState();
00567 }
00568
00569 void InterleavedSearcher::update(ExecutionState *current,
00570 const std::set<ExecutionState*> &addedStates,
00571 const std::set<ExecutionState*> &removedStates) {
00572 for (std::vector<Searcher*>::const_iterator it = searchers.begin(),
00573 ie = searchers.end(); it != ie; ++it)
00574 (*it)->update(current, addedStates, removedStates);
00575 }