void StatsTracker::stepInstruction(ExecutionState &es) { if (OutputIStats) { if (TrackInstructionTime) { static sys::TimeValue lastNowTime(0,0),lastUserTime(0,0); if (lastUserTime.seconds()==0 && lastUserTime.nanoseconds()==0) { sys::TimeValue sys(0,0); sys::Process::GetTimeUsage(lastNowTime,lastUserTime,sys); } else { sys::TimeValue now(0,0),user(0,0),sys(0,0); sys::Process::GetTimeUsage(now,user,sys); sys::TimeValue delta = user - lastUserTime; sys::TimeValue deltaNow = now - lastNowTime; stats::instructionTime += delta.usec(); stats::instructionRealTime += deltaNow.usec(); lastUserTime = user; lastNowTime = now; } } Instruction *inst = es.pc->inst; const InstructionInfo &ii = *es.pc->info; StackFrame &sf = es.stack.back(); theStatisticManager->setIndex(ii.id); if (UseCallPaths) theStatisticManager->setContext(&sf.callPathNode->statistics); if (es.instsSinceCovNew) ++es.instsSinceCovNew; if (sf.kf->trackCoverage && instructionIsCoverable(inst)) { if (!theStatisticManager->getIndexedValue(stats::coveredInstructions, ii.id)) { // Checking for actual stoppoints avoids inconsistencies due // to line number propogation. // // FIXME: This trick no longer works, we should fix this in the line // number propogation. #if (LLVM_VERSION_MAJOR == 2 && LLVM_VERSION_MINOR < 7) if (isa<DbgStopPointInst>(inst)) #endif es.coveredLines[&ii.file].insert(ii.line); es.coveredNew = true; es.instsSinceCovNew = 1; ++stats::coveredInstructions; stats::uncoveredInstructions += (uint64_t)-1; } } } }
void StatsTracker::stepInstruction(ExecutionState &es) { if (OutputIStats) { if (TrackInstructionTime) { static sys::TimeValue lastNowTime(0, 0), lastUserTime(0, 0); if (lastUserTime.seconds() == 0 && lastUserTime.nanoseconds() == 0) { sys::TimeValue sys(0, 0); sys::Process::GetTimeUsage(lastNowTime, lastUserTime, sys); } else { sys::TimeValue now(0, 0), user(0, 0), sys(0, 0); sys::Process::GetTimeUsage(now, user, sys); sys::TimeValue delta = user - lastUserTime; sys::TimeValue deltaNow = now - lastNowTime; stats::instructionTime += delta.usec(); stats::instructionRealTime += deltaNow.usec(); lastUserTime = user; lastNowTime = now; } } Instruction *inst = es.pc()->inst; const InstructionInfo &ii = *es.pc()->info; StackFrame &sf = es.stack().back(); theStatisticManager->setIndex(ii.id); if (UseCallPaths) theStatisticManager->setContext(&sf.callPathNode->statistics); if (es.instsSinceCovNew) ++es.instsSinceCovNew; if (instructionIsCoverable(inst)) { if (!theStatisticManager->getIndexedValue( stats::locallyCoveredInstructions, ii.id)) { // Checking for actual stoppoints avoids inconsistencies due // to line number propogation. es.coveredLines[&ii.file].insert(ii.line); es.setCoveredNew(); es.instsSinceCovNew = 1; ++stats::locallyCoveredInstructions; stats::locallyUncoveredInstructions += (uint64_t) -1; if (!theStatisticManager->getIndexedValue(stats::globallyCoveredInstructions, ii.id)) { ++stats::globallyCoveredInstructions; stats::globallyUncoveredInstructions += (uint64_t) -1; } } } } }
StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, bool _updateMinDistToUncovered) : executor(_executor), objectFilename(_objectFilename), statsFile(0), istatsFile(0), startWallTime(util::getWallTime()), numBranches(0), fullBranches(0), partialBranches(0), updateMinDistToUncovered(_updateMinDistToUncovered) { KModule *km = executor.kmodule; if (!sys::path::is_absolute(objectFilename)) { SmallString<128> current(objectFilename); if(sys::fs::make_absolute(current)) { bool exists = false; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) Twine current_twine(current.str()); //requires a twine for this. so silly if (!sys::fs::exists(current_twine)) { #elif LLVM_VERSION_CODE == LLVM_VERSION(3, 5) if (!sys::fs::exists(current.str(), exists)) { #elif LLVM_VERSION_CODE < LLVM_VERSION(3, 5) error_code ec = sys::fs::exists(current.str(), exists); if (ec == errc::success && exists) { #endif objectFilename = current.c_str(); } } } if (OutputIStats) theStatisticManager->useIndexedStats(km->infos->getMaxID()); for (std::vector<KFunction*>::iterator it = km->functions.begin(), ie = km->functions.end(); it != ie; ++it) { KFunction *kf = *it; kf->trackCoverage = 1; for (unsigned i=0; i<kf->numInstructions; ++i) { KInstruction *ki = kf->instructions[i]; if (OutputIStats) { unsigned id = ki->info->id; theStatisticManager->setIndex(id); if (kf->trackCoverage && instructionIsCoverable(ki->inst)) ++stats::uncoveredInstructions; } if (kf->trackCoverage) { if (BranchInst *bi = dyn_cast<BranchInst>(ki->inst)) if (!bi->isUnconditional()) numBranches++; } } } if (OutputStats) { statsFile = executor.interpreterHandler->openOutputFile("run.stats"); assert(statsFile && "unable to open statistics trace file"); writeStatsHeader(); writeStatsLine(); executor.addTimer(new WriteStatsTimer(this), StatsWriteInterval); if (updateMinDistToUncovered) { computeReachableUncovered(); executor.addTimer(new UpdateReachableTimer(this), UncoveredUpdateInterval); } } if (OutputIStats) { istatsFile = executor.interpreterHandler->openOutputFile("run.istats"); assert(istatsFile && "unable to open istats file"); executor.addTimer(new WriteIStatsTimer(this), IStatsWriteInterval); } } StatsTracker::~StatsTracker() { if (statsFile) delete statsFile; if (istatsFile) delete istatsFile; } void StatsTracker::done() { if (statsFile) writeStatsLine(); if (OutputIStats) writeIStats(); } void StatsTracker::stepInstruction(ExecutionState &es) { if (OutputIStats) { if (TrackInstructionTime) { static sys::TimeValue lastNowTime(0,0),lastUserTime(0,0); if (lastUserTime.seconds()==0 && lastUserTime.nanoseconds()==0) { sys::TimeValue sys(0,0); sys::Process::GetTimeUsage(lastNowTime,lastUserTime,sys); } else { sys::TimeValue now(0,0),user(0,0),sys(0,0); sys::Process::GetTimeUsage(now,user,sys); sys::TimeValue delta = user - lastUserTime; sys::TimeValue deltaNow = now - lastNowTime; stats::instructionTime += delta.usec(); stats::instructionRealTime += deltaNow.usec(); lastUserTime = user; lastNowTime = now; } } Instruction *inst = es.pc->inst; const InstructionInfo &ii = *es.pc->info; StackFrame &sf = es.stack.back(); theStatisticManager->setIndex(ii.id); if (UseCallPaths) theStatisticManager->setContext(&sf.callPathNode->statistics); if (es.instsSinceCovNew) ++es.instsSinceCovNew; if (sf.kf->trackCoverage && instructionIsCoverable(inst)) { if (!theStatisticManager->getIndexedValue(stats::coveredInstructions, ii.id)) { // Checking for actual stoppoints avoids inconsistencies due // to line number propogation. // // FIXME: This trick no longer works, we should fix this in the line // number propogation. es.coveredLines[&ii.file].insert(ii.line); es.coveredNew = true; es.instsSinceCovNew = 1; ++stats::coveredInstructions; stats::uncoveredInstructions += (uint64_t)-1; } } } } /// /* Should be called _after_ the es->pushFrame() */ void StatsTracker::framePushed(ExecutionState &es, StackFrame *parentFrame) { if (OutputIStats) { StackFrame &sf = es.stack.back(); if (UseCallPaths) { CallPathNode *parent = parentFrame ? parentFrame->callPathNode : 0; CallPathNode *cp = callPathManager.getCallPath(parent, sf.caller ? sf.caller->inst : 0, sf.kf->function); sf.callPathNode = cp; cp->count++; } if (updateMinDistToUncovered) { uint64_t minDistAtRA = 0; if (parentFrame) minDistAtRA = parentFrame->minDistToUncoveredOnReturn; sf.minDistToUncoveredOnReturn = sf.caller ? computeMinDistToUncovered(sf.caller, minDistAtRA) : 0; } } } /* Should be called _after_ the es->popFrame() */ void StatsTracker::framePopped(ExecutionState &es) { // XXX remove me? } void StatsTracker::markBranchVisited(ExecutionState *visitedTrue, ExecutionState *visitedFalse) { if (OutputIStats) { unsigned id = theStatisticManager->getIndex(); uint64_t hasTrue = theStatisticManager->getIndexedValue(stats::trueBranches, id); uint64_t hasFalse = theStatisticManager->getIndexedValue(stats::falseBranches, id); if (visitedTrue && !hasTrue) { visitedTrue->coveredNew = true; visitedTrue->instsSinceCovNew = 1; ++stats::trueBranches; if (hasFalse) { ++fullBranches; --partialBranches; } else ++partialBranches; hasTrue = 1; } if (visitedFalse && !hasFalse) { visitedFalse->coveredNew = true; visitedFalse->instsSinceCovNew = 1; ++stats::falseBranches; if (hasTrue) { ++fullBranches; --partialBranches; } else ++partialBranches; } } } void StatsTracker::writeStatsHeader() { *statsFile << "('Instructions'," << "'FullBranches'," << "'PartialBranches'," << "'NumBranches'," << "'UserTime'," << "'NumStates'," << "'MallocUsage'," << "'NumQueries'," << "'NumQueryConstructs'," << "'NumObjects'," << "'WallTime'," << "'CoveredInstructions'," << "'UncoveredInstructions'," << "'QueryTime'," << "'SolverTime'," << "'CexCacheTime'," << "'ForkTime'," << "'ResolveTime'," #ifdef DEBUG << "'ArrayHashTime'," #endif << ")\n"; statsFile->flush(); }