00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Common.h"
00011
00012 #include "StatsTracker.h"
00013
00014 #include "klee/ExecutionState.h"
00015 #include "klee/Statistics.h"
00016 #include "klee/Internal/Module/InstructionInfoTable.h"
00017 #include "klee/Internal/Module/KModule.h"
00018 #include "klee/Internal/Module/KInstruction.h"
00019 #include "klee/Internal/Support/ModuleUtil.h"
00020 #include "klee/Internal/System/Time.h"
00021
00022 #include "CallPathManager.h"
00023 #include "CoreStats.h"
00024 #include "Executor.h"
00025 #include "MemoryManager.h"
00026 #include "UserSearcher.h"
00027 #include "../Solver/SolverStats.h"
00028
00029 #include "llvm/BasicBlock.h"
00030 #include "llvm/Function.h"
00031 #include "llvm/Instructions.h"
00032 #include "llvm/IntrinsicInst.h"
00033 #include "llvm/InlineAsm.h"
00034 #include "llvm/Module.h"
00035 #include "llvm/Type.h"
00036 #include "llvm/Support/CommandLine.h"
00037 #include "llvm/Support/CFG.h"
00038 #include "llvm/System/Process.h"
00039 #include "llvm/System/Path.h"
00040
00041 #include <iostream>
00042 #include <fstream>
00043
00044 using namespace klee;
00045 using namespace llvm;
00046
00048
00049 namespace {
00050 cl::opt<bool>
00051 TrackInstructionTime("track-instruction-time",
00052 cl::desc("Enable tracking of time for individual instructions"),
00053 cl::init(false));
00054
00055 cl::opt<bool>
00056 OutputStats("output-stats",
00057 cl::desc("Write running stats trace file"),
00058 cl::init(true));
00059
00060 cl::opt<bool>
00061 OutputIStats("output-istats",
00062 cl::desc("Write instruction level statistics (in callgrind format)"),
00063 cl::init(true));
00064
00065 cl::opt<double>
00066 StatsWriteInterval("stats-write-interval",
00067 cl::desc("Approximate number of seconds between stats writes (default: 1.0)"),
00068 cl::init(1.));
00069
00070 cl::opt<double>
00071 IStatsWriteInterval("istats-write-interval",
00072 cl::desc("Approximate number of seconds between istats writes (default: 10.0)"),
00073 cl::init(10.));
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 cl::opt<double>
00084 UncoveredUpdateInterval("uncovered-update-interval",
00085 cl::init(30.));
00086
00087 cl::opt<bool>
00088 UseCallPaths("use-call-paths",
00089 cl::desc("Enable calltree tracking for instruction level statistics"),
00090 cl::init(true));
00091
00092 }
00093
00095
00096 bool StatsTracker::useStatistics() {
00097 return OutputStats || OutputIStats;
00098 }
00099
00100 namespace klee {
00101 class WriteIStatsTimer : public Executor::Timer {
00102 StatsTracker *statsTracker;
00103
00104 public:
00105 WriteIStatsTimer(StatsTracker *_statsTracker) : statsTracker(_statsTracker) {}
00106 ~WriteIStatsTimer() {}
00107
00108 void run() { statsTracker->writeIStats(); }
00109 };
00110
00111 class WriteStatsTimer : public Executor::Timer {
00112 StatsTracker *statsTracker;
00113
00114 public:
00115 WriteStatsTimer(StatsTracker *_statsTracker) : statsTracker(_statsTracker) {}
00116 ~WriteStatsTimer() {}
00117
00118 void run() { statsTracker->writeStatsLine(); }
00119 };
00120
00121 class UpdateReachableTimer : public Executor::Timer {
00122 StatsTracker *statsTracker;
00123
00124 public:
00125 UpdateReachableTimer(StatsTracker *_statsTracker) : statsTracker(_statsTracker) {}
00126
00127 void run() { statsTracker->computeReachableUncovered(); }
00128 };
00129
00130 }
00131
00132
00133
00138 static bool instructionIsCoverable(Instruction *i) {
00139 if (i->getOpcode() == Instruction::Unreachable) {
00140 BasicBlock *bb = i->getParent();
00141 BasicBlock::iterator it(i);
00142 if (it==bb->begin()) {
00143 return true;
00144 } else {
00145 Instruction *prev = --it;
00146 if (isa<CallInst>(prev) || isa<InvokeInst>(prev)) {
00147 Function *target = getDirectCallTarget(prev);
00148 if (target && target->doesNotReturn())
00149 return false;
00150 }
00151 }
00152 }
00153
00154 return true;
00155 }
00156
00157 StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename,
00158 bool _updateMinDistToUncovered)
00159 : executor(_executor),
00160 objectFilename(_objectFilename),
00161 statsFile(0),
00162 istatsFile(0),
00163 startWallTime(util::getWallTime()),
00164 numBranches(0),
00165 fullBranches(0),
00166 partialBranches(0),
00167 updateMinDistToUncovered(_updateMinDistToUncovered) {
00168 KModule *km = executor.kmodule;
00169
00170 sys::Path module(objectFilename);
00171 if (!sys::Path(objectFilename).isAbsolute()) {
00172 sys::Path current = sys::Path::GetCurrentDirectory();
00173 current.appendComponent(objectFilename);
00174 if (current.exists())
00175 objectFilename = current.c_str();
00176 }
00177
00178 if (OutputIStats)
00179 theStatisticManager->useIndexedStats(km->infos->getMaxID());
00180
00181 for (std::vector<KFunction*>::iterator it = km->functions.begin(),
00182 ie = km->functions.end(); it != ie; ++it) {
00183 KFunction *kf = *it;
00184 kf->trackCoverage = 1;
00185
00186 for (unsigned i=0; i<kf->numInstructions; ++i) {
00187 KInstruction *ki = kf->instructions[i];
00188
00189 if (OutputIStats) {
00190 unsigned id = ki->info->id;
00191 theStatisticManager->setIndex(id);
00192 if (kf->trackCoverage && instructionIsCoverable(ki->inst))
00193 ++stats::uncoveredInstructions;
00194 }
00195
00196 if (kf->trackCoverage) {
00197 if (BranchInst *bi = dyn_cast<BranchInst>(ki->inst))
00198 if (!bi->isUnconditional())
00199 numBranches++;
00200 }
00201 }
00202 }
00203
00204 if (OutputStats) {
00205 statsFile = executor.interpreterHandler->openOutputFile("run.stats");
00206 assert(statsFile && "unable to open statistics trace file");
00207 writeStatsHeader();
00208 writeStatsLine();
00209
00210 executor.addTimer(new WriteStatsTimer(this), StatsWriteInterval);
00211
00212 if (updateMinDistToUncovered)
00213 executor.addTimer(new UpdateReachableTimer(this), UncoveredUpdateInterval);
00214 }
00215
00216 if (OutputIStats) {
00217 istatsFile = executor.interpreterHandler->openOutputFile("run.istats");
00218 assert(istatsFile && "unable to open istats file");
00219
00220 executor.addTimer(new WriteIStatsTimer(this), IStatsWriteInterval);
00221 }
00222 }
00223
00224 StatsTracker::~StatsTracker() {
00225 if (statsFile)
00226 delete statsFile;
00227 if (istatsFile)
00228 delete istatsFile;
00229 }
00230
00231 void StatsTracker::done() {
00232 if (statsFile)
00233 writeStatsLine();
00234 if (OutputIStats)
00235 writeIStats();
00236 }
00237
00238 void StatsTracker::stepInstruction(ExecutionState &es) {
00239 if (OutputIStats) {
00240 if (TrackInstructionTime) {
00241 static sys::TimeValue lastNowTime(0,0),lastUserTime(0,0);
00242
00243 if (lastUserTime.seconds()==0 && lastUserTime.nanoseconds()==0) {
00244 sys::TimeValue sys(0,0);
00245 sys::Process::GetTimeUsage(lastNowTime,lastUserTime,sys);
00246 } else {
00247 sys::TimeValue now(0,0),user(0,0),sys(0,0);
00248 sys::Process::GetTimeUsage(now,user,sys);
00249 sys::TimeValue delta = user - lastUserTime;
00250 sys::TimeValue deltaNow = now - lastNowTime;
00251 stats::instructionTime += delta.usec();
00252 stats::instructionRealTime += deltaNow.usec();
00253 lastUserTime = user;
00254 lastNowTime = now;
00255 }
00256 }
00257
00258 Instruction *inst = es.pc->inst;
00259 const InstructionInfo &ii = *es.pc->info;
00260 StackFrame &sf = es.stack.back();
00261 theStatisticManager->setIndex(ii.id);
00262 if (UseCallPaths)
00263 theStatisticManager->setContext(&sf.callPathNode->statistics);
00264
00265 if (es.instsSinceCovNew)
00266 ++es.instsSinceCovNew;
00267
00268 if (sf.kf->trackCoverage && instructionIsCoverable(inst)) {
00269 if (!theStatisticManager->getIndexedValue(stats::coveredInstructions, ii.id)) {
00270
00271
00272 if (isa<DbgStopPointInst>(inst))
00273 es.coveredLines[&ii.file].insert(ii.line);
00274 es.coveredNew = true;
00275 es.instsSinceCovNew = 1;
00276 ++stats::coveredInstructions;
00277 stats::uncoveredInstructions += (uint64_t)-1;
00278 }
00279 }
00280 }
00281 }
00282
00284
00285
00286 void StatsTracker::framePushed(ExecutionState &es, StackFrame *parentFrame) {
00287 if (OutputIStats) {
00288 StackFrame &sf = es.stack.back();
00289
00290 if (UseCallPaths) {
00291 CallPathNode *parent = parentFrame ? parentFrame->callPathNode : 0;
00292 CallPathNode *cp = callPathManager.getCallPath(parent,
00293 sf.caller ? sf.caller->inst : 0,
00294 sf.kf->function);
00295 sf.callPathNode = cp;
00296 cp->count++;
00297 }
00298
00299 if (updateMinDistToUncovered) {
00300 uint64_t minDistAtRA = 0;
00301 if (parentFrame)
00302 minDistAtRA = parentFrame->minDistToUncoveredOnReturn;
00303
00304 sf.minDistToUncoveredOnReturn = sf.caller ?
00305 computeMinDistToUncovered(sf.caller, minDistAtRA) : 0;
00306 }
00307 }
00308 }
00309
00310
00311 void StatsTracker::framePopped(ExecutionState &es) {
00312
00313 }
00314
00315
00316 void StatsTracker::markBranchVisited(ExecutionState *visitedTrue,
00317 ExecutionState *visitedFalse) {
00318 if (OutputIStats) {
00319 unsigned id = theStatisticManager->getIndex();
00320 uint64_t hasTrue = theStatisticManager->getIndexedValue(stats::trueBranches, id);
00321 uint64_t hasFalse = theStatisticManager->getIndexedValue(stats::falseBranches, id);
00322 if (visitedTrue && !hasTrue) {
00323 visitedTrue->coveredNew = true;
00324 visitedTrue->instsSinceCovNew = 1;
00325 ++stats::trueBranches;
00326 if (hasFalse) { ++fullBranches; --partialBranches; }
00327 else ++partialBranches;
00328 hasTrue = 1;
00329 }
00330 if (visitedFalse && !hasFalse) {
00331 visitedFalse->coveredNew = true;
00332 visitedFalse->instsSinceCovNew = 1;
00333 ++stats::falseBranches;
00334 if (hasTrue) { ++fullBranches; --partialBranches; }
00335 else ++partialBranches;
00336 }
00337 }
00338 }
00339
00340 void StatsTracker::writeStatsHeader() {
00341 *statsFile << "('Instructions',"
00342 << "'FullBranches',"
00343 << "'PartialBranches',"
00344 << "'NumBranches',"
00345 << "'UserTime',"
00346 << "'NumStates',"
00347 << "'MallocUsage',"
00348 << "'NumQueries',"
00349 << "'NumQueryConstructs',"
00350 << "'NumObjects',"
00351 << "'WallTime',"
00352 << "'CoveredInstructions',"
00353 << "'UncoveredInstructions',"
00354 << "'QueryTime',"
00355 << "'SolverTime',"
00356 << "'CexCacheTime',"
00357 << "'ForkTime',"
00358 << "'ResolveTime',"
00359 << ")\n";
00360 statsFile->flush();
00361 }
00362
00363 double StatsTracker::elapsed() {
00364 return util::getWallTime() - startWallTime;
00365 }
00366
00367 void StatsTracker::writeStatsLine() {
00368 *statsFile << "(" << stats::instructions
00369 << "," << fullBranches
00370 << "," << partialBranches
00371 << "," << numBranches
00372 << "," << util::getUserTime()
00373 << "," << executor.states.size()
00374 << "," << sys::Process::GetTotalMemoryUsage()
00375 << "," << stats::queries
00376 << "," << stats::queryConstructs
00377 << "," << 0
00378 << "," << elapsed()
00379 << "," << stats::coveredInstructions
00380 << "," << stats::uncoveredInstructions
00381 << "," << stats::queryTime / 1000000.
00382 << "," << stats::solverTime / 1000000.
00383 << "," << stats::cexCacheTime / 1000000.
00384 << "," << stats::forkTime / 1000000.
00385 << "," << stats::resolveTime / 1000000.
00386 << ")\n";
00387 statsFile->flush();
00388 }
00389
00390 void StatsTracker::updateStateStatistics(uint64_t addend) {
00391 for (std::set<ExecutionState*>::iterator it = executor.states.begin(),
00392 ie = executor.states.end(); it != ie; ++it) {
00393 ExecutionState &state = **it;
00394 const InstructionInfo &ii = *state.pc->info;
00395 theStatisticManager->incrementIndexedValue(stats::states, ii.id, addend);
00396 if (UseCallPaths)
00397 state.stack.back().callPathNode->statistics.incrementValue(stats::states, addend);
00398 }
00399 }
00400
00401 void StatsTracker::writeIStats() {
00402 Module *m = executor.kmodule->module;
00403 uint64_t istatsMask = 0;
00404 std::ostream &of = *istatsFile;
00405
00406 of.seekp(0, std::ios::end);
00407 unsigned istatsSize = of.tellp();
00408 of.seekp(0);
00409
00410 of << "version: 1\n";
00411 of << "creator: klee\n";
00412 of << "pid: " << sys::Process::GetCurrentUserId() << "\n";
00413 of << "cmd: " << m->getModuleIdentifier() << "\n\n";
00414 of << "\n";
00415
00416 StatisticManager &sm = *theStatisticManager;
00417 unsigned nStats = sm.getNumStatistics();
00418
00419
00420 istatsMask |= 1<<sm.getStatisticID("Queries");
00421 istatsMask |= 1<<sm.getStatisticID("QueriesValid");
00422 istatsMask |= 1<<sm.getStatisticID("QueriesInvalid");
00423 istatsMask |= 1<<sm.getStatisticID("QueryTime");
00424 istatsMask |= 1<<sm.getStatisticID("ResolveTime");
00425 istatsMask |= 1<<sm.getStatisticID("Instructions");
00426 istatsMask |= 1<<sm.getStatisticID("InstructionTimes");
00427 istatsMask |= 1<<sm.getStatisticID("InstructionRealTimes");
00428 istatsMask |= 1<<sm.getStatisticID("Forks");
00429 istatsMask |= 1<<sm.getStatisticID("CoveredInstructions");
00430 istatsMask |= 1<<sm.getStatisticID("UncoveredInstructions");
00431 istatsMask |= 1<<sm.getStatisticID("States");
00432 istatsMask |= 1<<sm.getStatisticID("MinDistToUncovered");
00433
00434 of << "positions: instr line\n";
00435
00436 for (unsigned i=0; i<nStats; i++) {
00437 if (istatsMask & (1<<i)) {
00438 Statistic &s = sm.getStatistic(i);
00439 of << "event: " << s.getShortName() << " : "
00440 << s.getName() << "\n";
00441 }
00442 }
00443
00444 of << "events: ";
00445 for (unsigned i=0; i<nStats; i++) {
00446 if (istatsMask & (1<<i))
00447 of << sm.getStatistic(i).getShortName() << " ";
00448 }
00449 of << "\n";
00450
00451
00452
00453 if (istatsMask & (1<<stats::states.getID()))
00454 updateStateStatistics(1);
00455
00456 std::string sourceFile = "";
00457
00458 CallSiteSummaryTable callSiteStats;
00459 if (UseCallPaths)
00460 callPathManager.getSummaryStatistics(callSiteStats);
00461
00462 of << "ob=" << objectFilename << "\n";
00463
00464 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
00465 fnIt != fn_ie; ++fnIt) {
00466 if (!fnIt->isDeclaration()) {
00467 of << "fn=" << fnIt->getName() << "\n";
00468 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
00469 bbIt != bb_ie; ++bbIt) {
00470 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
00471 it != ie; ++it) {
00472 Instruction *instr = &*it;
00473 const InstructionInfo &ii = executor.kmodule->infos->getInfo(instr);
00474 unsigned index = ii.id;
00475 if (ii.file!=sourceFile) {
00476 of << "fl=" << ii.file << "\n";
00477 sourceFile = ii.file;
00478 }
00479 of << ii.assemblyLine << " ";
00480 of << ii.line << " ";
00481 for (unsigned i=0; i<nStats; i++)
00482 if (istatsMask&(1<<i))
00483 of << sm.getIndexedValue(sm.getStatistic(i), index) << " ";
00484 of << "\n";
00485
00486 if (UseCallPaths &&
00487 (isa<CallInst>(instr) || isa<InvokeInst>(instr))) {
00488 CallSiteSummaryTable::iterator it = callSiteStats.find(instr);
00489 if (it!=callSiteStats.end()) {
00490 for (std::map<llvm::Function*, CallSiteInfo>::iterator
00491 fit = it->second.begin(), fie = it->second.end();
00492 fit != fie; ++fit) {
00493 Function *f = fit->first;
00494 CallSiteInfo &csi = fit->second;
00495 const InstructionInfo &fii =
00496 executor.kmodule->infos->getFunctionInfo(f);
00497
00498 if (fii.file!="" && fii.file!=sourceFile)
00499 of << "cfl=" << fii.file << "\n";
00500 of << "cfn=" << f->getName() << "\n";
00501 of << "calls=" << csi.count << " ";
00502 of << fii.assemblyLine << " ";
00503 of << fii.line << "\n";
00504
00505 of << ii.assemblyLine << " ";
00506 of << ii.line << " ";
00507 for (unsigned i=0; i<nStats; i++) {
00508 if (istatsMask&(1<<i)) {
00509 Statistic &s = sm.getStatistic(i);
00510 uint64_t value;
00511
00512
00513
00514 if (&s == &stats::uncoveredInstructions) {
00515 value = 0;
00516 } else {
00517 value = csi.statistics.getValue(s);
00518 }
00519
00520 of << value << " ";
00521 }
00522 }
00523 of << "\n";
00524 }
00525 }
00526 }
00527 }
00528 }
00529 }
00530 }
00531
00532 if (istatsMask & (1<<stats::states.getID()))
00533 updateStateStatistics((uint64_t)-1);
00534
00535
00536 unsigned pos = of.tellp();
00537 for (unsigned i=pos; i<istatsSize; ++i)
00538 of << '\n';
00539
00540 of.flush();
00541 }
00542
00544
00545 typedef std::map<Instruction*, std::vector<Function*> > calltargets_ty;
00546
00547 static calltargets_ty callTargets;
00548 static std::map<Function*, std::vector<Instruction*> > functionCallers;
00549 static std::map<Function*, unsigned> functionShortestPath;
00550
00551 static std::vector<Instruction*> getSuccs(Instruction *i) {
00552 BasicBlock *bb = i->getParent();
00553 std::vector<Instruction*> res;
00554
00555 if (i==bb->getTerminator()) {
00556 for (succ_iterator it = succ_begin(bb), ie = succ_end(bb); it != ie; ++it)
00557 res.push_back(it->begin());
00558 } else {
00559 res.push_back(++BasicBlock::iterator(i));
00560 }
00561
00562 return res;
00563 }
00564
00565 uint64_t klee::computeMinDistToUncovered(const KInstruction *ki,
00566 uint64_t minDistAtRA) {
00567 StatisticManager &sm = *theStatisticManager;
00568 if (minDistAtRA==0) {
00569 return sm.getIndexedValue(stats::minDistToUncovered,
00570 ki->info->id);
00571 } else {
00572 uint64_t minDistLocal = sm.getIndexedValue(stats::minDistToUncovered,
00573 ki->info->id);
00574 uint64_t distToReturn = sm.getIndexedValue(stats::minDistToReturn,
00575 ki->info->id);
00576
00577 if (distToReturn==0) {
00578 return minDistLocal;
00579 } else if (!minDistLocal) {
00580 return distToReturn + minDistAtRA;
00581 } else {
00582 return std::min(minDistLocal, distToReturn + minDistAtRA);
00583 }
00584 }
00585 }
00586
00587 void StatsTracker::computeReachableUncovered() {
00588 KModule *km = executor.kmodule;
00589 Module *m = km->module;
00590 static bool init = true;
00591 const InstructionInfoTable &infos = *km->infos;
00592 StatisticManager &sm = *theStatisticManager;
00593
00594 if (init) {
00595 init = false;
00596
00597
00598
00599
00600 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
00601 fnIt != fn_ie; ++fnIt) {
00602 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
00603 bbIt != bb_ie; ++bbIt) {
00604 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
00605 it != it; ++it) {
00606 if (isa<CallInst>(it) || isa<InvokeInst>(it)) {
00607 if (isa<InlineAsm>(it->getOperand(0))) {
00608
00609
00610 callTargets.insert(std::make_pair(it,
00611 std::vector<Function*>()));
00612 } else if (Function *target = getDirectCallTarget(it)) {
00613 callTargets[it].push_back(target);
00614 } else {
00615 callTargets[it] =
00616 std::vector<Function*>(km->escapingFunctions.begin(),
00617 km->escapingFunctions.end());
00618 }
00619 }
00620 }
00621 }
00622 }
00623
00624
00625 for (calltargets_ty::iterator it = callTargets.begin(),
00626 ie = callTargets.end(); it != ie; ++it)
00627 for (std::vector<Function*>::iterator fit = it->second.begin(),
00628 fie = it->second.end(); fit != fie; ++fit)
00629 functionCallers[*fit].push_back(it->first);
00630
00631
00632
00633 std::vector<Instruction *> instructions;
00634 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
00635 fnIt != fn_ie; ++fnIt) {
00636 if (fnIt->isDeclaration()) {
00637 if (fnIt->doesNotReturn()) {
00638 functionShortestPath[fnIt] = 0;
00639 } else {
00640 functionShortestPath[fnIt] = 1;
00641 }
00642 } else {
00643 functionShortestPath[fnIt] = 0;
00644 }
00645
00646
00647 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
00648 bbIt != bb_ie; ++bbIt) {
00649 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
00650 it != it; ++it) {
00651 instructions.push_back(it);
00652 unsigned id = infos.getInfo(it).id;
00653 sm.setIndexedValue(stats::minDistToReturn,
00654 id,
00655 isa<ReturnInst>(it) || isa<UnwindInst>(it));
00656 }
00657 }
00658 }
00659
00660 std::reverse(instructions.begin(), instructions.end());
00661
00662
00663 bool changed;
00664 do {
00665 changed = false;
00666 for (std::vector<Instruction*>::iterator it = instructions.begin(),
00667 ie = instructions.end(); it != ie; ++it) {
00668 Instruction *inst = *it;
00669 unsigned bestThrough = 0;
00670
00671 if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
00672 std::vector<Function*> &targets = callTargets[inst];
00673 for (std::vector<Function*>::iterator fnIt = targets.begin(),
00674 ie = targets.end(); fnIt != ie; ++fnIt) {
00675 uint64_t dist = functionShortestPath[*fnIt];
00676 if (dist) {
00677 dist = 1+dist;
00678 if (bestThrough==0 || dist<bestThrough)
00679 bestThrough = dist;
00680 }
00681 }
00682 } else {
00683 bestThrough = 1;
00684 }
00685
00686 if (bestThrough) {
00687 unsigned id = infos.getInfo(*it).id;
00688 uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToReturn, id);
00689 std::vector<Instruction*> succs = getSuccs(*it);
00690 for (std::vector<Instruction*>::iterator it2 = succs.begin(),
00691 ie = succs.end(); it2 != ie; ++it2) {
00692 uint64_t dist = sm.getIndexedValue(stats::minDistToReturn,
00693 infos.getInfo(*it2).id);
00694 if (dist) {
00695 uint64_t val = bestThrough + dist;
00696 if (best==0 || val<best)
00697 best = val;
00698 }
00699 }
00700 if (best != cur) {
00701 sm.setIndexedValue(stats::minDistToReturn, id, best);
00702 changed = true;
00703
00704
00705 Function *f = inst->getParent()->getParent();
00706 if (inst==f->begin()->begin())
00707 functionShortestPath[f] = best;
00708 }
00709 }
00710 }
00711 } while (changed);
00712 }
00713
00714
00715 std::vector<Instruction *> instructions;
00716 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
00717 fnIt != fn_ie; ++fnIt) {
00718
00719 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
00720 bbIt != bb_ie; ++bbIt) {
00721 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
00722 it != it; ++it) {
00723 unsigned id = infos.getInfo(it).id;
00724 instructions.push_back(&*it);
00725 sm.setIndexedValue(stats::minDistToUncovered,
00726 id,
00727 sm.getIndexedValue(stats::uncoveredInstructions, id));
00728 }
00729 }
00730 }
00731
00732 std::reverse(instructions.begin(), instructions.end());
00733
00734
00735 bool changed;
00736 do {
00737 changed = false;
00738 for (std::vector<Instruction*>::iterator it = instructions.begin(),
00739 ie = instructions.end(); it != ie; ++it) {
00740 Instruction *inst = *it;
00741 uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToUncovered,
00742 infos.getInfo(inst).id);
00743 unsigned bestThrough = 0;
00744
00745 if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
00746 std::vector<Function*> &targets = callTargets[inst];
00747 for (std::vector<Function*>::iterator fnIt = targets.begin(),
00748 ie = targets.end(); fnIt != ie; ++fnIt) {
00749 uint64_t dist = functionShortestPath[*fnIt];
00750 if (dist) {
00751 dist = 1+dist;
00752 if (bestThrough==0 || dist<bestThrough)
00753 bestThrough = dist;
00754 }
00755
00756 if (!(*fnIt)->isDeclaration()) {
00757 uint64_t calleeDist = sm.getIndexedValue(stats::minDistToUncovered,
00758 infos.getFunctionInfo(*fnIt).id);
00759 if (calleeDist) {
00760 calleeDist = 1+calleeDist;
00761 if (best==0 || calleeDist<best)
00762 best = calleeDist;
00763 }
00764 }
00765 }
00766 } else {
00767 bestThrough = 1;
00768 }
00769
00770 if (bestThrough) {
00771 std::vector<Instruction*> succs = getSuccs(inst);
00772 for (std::vector<Instruction*>::iterator it2 = succs.begin(),
00773 ie = succs.end(); it2 != ie; ++it2) {
00774 uint64_t dist = sm.getIndexedValue(stats::minDistToUncovered,
00775 infos.getInfo(*it2).id);
00776 if (dist) {
00777 uint64_t val = bestThrough + dist;
00778 if (best==0 || val<best)
00779 best = val;
00780 }
00781 }
00782 }
00783
00784 if (best != cur) {
00785 sm.setIndexedValue(stats::minDistToUncovered,
00786 infos.getInfo(inst).id,
00787 best);
00788 changed = true;
00789 }
00790 }
00791 } while (changed);
00792
00793 for (std::set<ExecutionState*>::iterator it = executor.states.begin(),
00794 ie = executor.states.end(); it != ie; ++it) {
00795 ExecutionState *es = *it;
00796 uint64_t currentFrameMinDist = 0;
00797 for (ExecutionState::stack_ty::iterator sfIt = es->stack.begin(),
00798 sf_ie = es->stack.end(); sfIt != sf_ie; ++sfIt) {
00799 ExecutionState::stack_ty::iterator next = sfIt + 1;
00800 KInstIterator kii;
00801
00802 if (next==es->stack.end()) {
00803 kii = es->pc;
00804 } else {
00805 kii = next->caller;
00806 ++kii;
00807 }
00808
00809 sfIt->minDistToUncoveredOnReturn = currentFrameMinDist;
00810
00811 currentFrameMinDist = computeMinDistToUncovered(kii, currentFrameMinDist);
00812 }
00813 }
00814 }