30#include "llvm/ADT/SmallBitVector.h"
31#include "llvm/IR/BasicBlock.h"
32#if LLVM_VERSION_CODE < LLVM_VERSION(8, 0)
33#include "llvm/IR/CallSite.h"
35#include "llvm/IR/CFG.h"
36#include "llvm/IR/Function.h"
37#include "llvm/IR/InlineAsm.h"
38#include "llvm/IR/Instructions.h"
39#include "llvm/IR/IntrinsicInst.h"
40#include "llvm/IR/Module.h"
41#include "llvm/IR/Type.h"
42#include "llvm/Support/CommandLine.h"
43#include "llvm/Support/FileSystem.h"
44#include "llvm/Support/Path.h"
45#include "llvm/Support/Process.h"
57 StatsCat(
"Statistics options",
58 "These options control the statistics generated by KLEE.");
60cl::opt<bool> TrackInstructionTime(
61 "track-instruction-time", cl::init(
false),
63 "Enable tracking of time for individual instructions (default=false)"),
67 OutputStats(
"output-stats", cl::init(
true),
68 cl::desc(
"Write running stats trace file (default=true)"),
71cl::opt<bool> OutputIStats(
"output-istats", cl::init(
true),
72 cl::desc(
"Write instruction level statistics in "
73 "callgrind format (default=true)"),
76cl::opt<std::string> StatsWriteInterval(
77 "stats-write-interval", cl::init(
"1s"),
78 cl::desc(
"Approximate time between stats writes (default=1s)"),
81cl::opt<unsigned> StatsWriteAfterInstructions(
82 "stats-write-after-instructions", cl::init(0),
84 "Write statistics after each n instructions, 0 to disable (default=0)"),
87 cl::opt<unsigned> CommitEvery(
88 "stats-commit-after", cl::init(0),
89 cl::desc(
"Commit the statistics every N writes. By default commit every "
90 "write with -stats-write-interval or every 1000 writes with "
91 "-stats-write-after-instructions. (default=0)"),
94cl::opt<std::string> IStatsWriteInterval(
95 "istats-write-interval", cl::init(
"10s"),
97 "Approximate number of seconds between istats writes (default=10s)"),
100cl::opt<unsigned> IStatsWriteAfterInstructions(
101 "istats-write-after-instructions", cl::init(0),
103 "Write istats after each n instructions, 0 to disable (default=0)"),
107cl::opt<std::string> UncoveredUpdateInterval(
108 "uncovered-update-interval", cl::init(
"30s"),
109 cl::desc(
"Update interval for uncovered instructions (default=30s)"),
112cl::opt<bool> UseCallPaths(
"use-call-paths", cl::init(
true),
113 cl::desc(
"Enable calltree tracking for instruction "
114 "level statistics (default=true)"),
121bool StatsTracker::useStatistics() {
122 return OutputStats || OutputIStats;
134 if (i->getOpcode() == Instruction::Unreachable) {
135 BasicBlock *bb = i->getParent();
136 BasicBlock::iterator it(i);
137 if (it==bb->begin()) {
140 Instruction *prev = &*(--it);
141 if (isa<CallInst>(prev) || isa<InvokeInst>(prev)) {
144 cast<CallBase>(*prev),
149 if (target && target->doesNotReturn())
159 std::ostringstream sstream;
160 sstream << prefix << sqlite3ErrMsg;
161 sqlite3_free(sqlite3ErrMsg);
162 return sstream.str();
166 bool _updateMinDistToUncovered)
167 : executor(_executor),
168 objectFilename(_objectFilename),
173 updateMinDistToUncovered(_updateMinDistToUncovered) {
175 const time::Span statsWriteInterval(StatsWriteInterval);
176 if (StatsWriteAfterInstructions > 0 && statsWriteInterval)
177 klee_error(
"Both options --stats-write-interval and "
178 "--stats-write-after-instructions cannot be enabled at the same "
181 const time::Span iStatsWriteInterval(IStatsWriteInterval);
182 if (IStatsWriteAfterInstructions > 0 && iStatsWriteInterval)
184 "Both options --istats-write-interval and "
185 "--istats-write-after-instructions cannot be enabled at the same "
189 if(CommitEvery > 0) {
197 if(sys::fs::make_absolute(current)) {
198 Twine current_twine(current.str());
199 if (!sys::fs::exists(current_twine)) {
216 unsigned id = ki->
info->
id;
223 if (BranchInst *bi = dyn_cast<BranchInst>(ki->
inst))
224 if (!bi->isUnconditional())
231 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
232 sqlite3_enable_shared_cache(0);
236 if (sqlite3_open(db_filename.c_str(), &
statsFile) != SQLITE_OK) {
237 std::ostringstream errorstream;
238 errorstream <<
"Can't open database: " << sqlite3_errmsg(
statsFile);
254 if (sqlite3_exec(
statsFile,
"PRAGMA synchronous = OFF",
nullptr,
nullptr, &zErrMsg) != SQLITE_OK) {
259 if (sqlite3_exec(
statsFile,
"PRAGMA journal_mode = WAL",
nullptr,
nullptr, &zErrMsg) != SQLITE_OK) {
268 if (rc != SQLITE_DONE) {
275 if (statsWriteInterval)
292 if (iStatsWriteInterval)
297 klee_error(
"Unable to open instruction level stats file (run.istats).");
305 if (rc != SQLITE_DONE) {
330 if (TrackInstructionTime) {
339 const auto delta = user - lastUserTime;
340 const auto deltaNow = now - lastNowTime;
348 Instruction *inst = es.
pc->
inst;
374 if (
statsFile && StatsWriteAfterInstructions &&
378 if (
istatsFile && IStatsWriteAfterInstructions &&
403 uint64_t minDistAtRA = 0;
423 if (visitedTrue && !hasTrue) {
431 if (visitedFalse && !hasFalse) {
442 std::ostringstream create, insert;
443 create <<
"CREATE TABLE stats ("
444 <<
"Instructions INTEGER,"
445 <<
"FullBranches INTEGER,"
446 <<
"PartialBranches INTEGER,"
447 <<
"NumBranches INTEGER,"
449 <<
"NumStates INTEGER,"
450 <<
"MallocUsage INTEGER,"
451 <<
"NumQueries INTEGER,"
452 <<
"NumQueryConstructs INTEGER,"
454 <<
"CoveredInstructions INTEGER,"
455 <<
"UncoveredInstructions INTEGER,"
456 <<
"QueryTime INTEGER,"
457 <<
"SolverTime INTEGER,"
458 <<
"CexCacheTime INTEGER,"
459 <<
"ForkTime INTEGER,"
460 <<
"ResolveTime INTEGER,"
461 <<
"QueryCexCacheMisses INTEGER,"
462 <<
"QueryCexCacheHits INTEGER,"
463 <<
"ArrayHashTime INTEGER"
465 char *zErrMsg =
nullptr;
466 if(sqlite3_exec(
statsFile, create.str().c_str(),
nullptr,
nullptr, &zErrMsg)) {
476 insert <<
"INSERT OR FAIL INTO stats ("
479 <<
"PartialBranches,"
485 <<
"NumQueryConstructs,"
487 <<
"CoveredInstructions,"
488 <<
"UncoveredInstructions,"
494 <<
"QueryCexCacheMisses,"
495 <<
"QueryCexCacheHits,"
520 if(sqlite3_prepare_v2(
statsFile, insert.str().c_str(), -1, &
insertStmt,
nullptr) != SQLITE_OK) {
549#ifdef KLEE_ARRAY_DEBUG
550 sqlite3_bind_int64(
insertStmt, 20, stats::arrayHashTime);
555 if(errCode != SQLITE_DONE)
klee_error(
"Error writing stats data: %s", sqlite3_errmsg(
statsFile));
572 for (std::set<ExecutionState*>::iterator it =
executor.
states.begin(),
587 unsigned istatsSize = of.tell();
591 of <<
"version: 1\n";
592 of <<
"creator: klee\n";
593 of <<
"pid: " << getpid() <<
"\n";
594 of <<
"cmd: " << m->getModuleIdentifier() <<
"\n\n";
599 llvm::SmallBitVector istatsMask(nStats);
615 of <<
"positions: instr line\n";
617 for (
unsigned i=0; i<nStats; i++) {
618 if (istatsMask.test(i)) {
626 for (
unsigned i=0; i<nStats; i++) {
627 if (istatsMask.test(i))
637 std::string sourceFile =
"";
643 of <<
"ob=" << llvm::sys::path::filename(
objectFilename).str() <<
"\n";
645 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
646 fnIt != fn_ie; ++fnIt) {
647 if (!fnIt->isDeclaration()) {
651 Function *fn = &*fnIt;
653 if (ii.
file != sourceFile) {
654 of <<
"fl=" << ii.
file <<
"\n";
655 sourceFile = ii.
file;
658 of <<
"fn=" << fnIt->getName().str() <<
"\n";
659 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
660 bbIt != bb_ie; ++bbIt) {
661 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
663 Instruction *instr = &*it;
665 unsigned index = ii.
id;
666 if (ii.
file!=sourceFile) {
667 of <<
"fl=" << ii.
file <<
"\n";
668 sourceFile = ii.
file;
671 of << ii.
line <<
" ";
672 for (
unsigned i=0; i<nStats; i++)
673 if (istatsMask.test(i))
678 (isa<CallInst>(instr) || isa<InvokeInst>(instr))) {
679 CallSiteSummaryTable::iterator it = callSiteStats.find(instr);
680 if (it!=callSiteStats.end()) {
681 for (
auto fit = it->second.begin(), fie = it->second.end();
683 const Function *f = fit->first;
688 if (fii.
file!=
"" && fii.
file!=sourceFile)
689 of <<
"cfl=" << fii.
file <<
"\n";
690 of <<
"cfn=" << f->getName().str() <<
"\n";
691 of <<
"calls=" << csi.
count <<
" ";
693 of << fii.
line <<
"\n";
696 of << ii.
line <<
" ";
697 for (
unsigned i=0; i<nStats; i++) {
698 if (istatsMask.test(i)) {
726 unsigned pos = of.tell();
727 for (
unsigned i=pos; i<istatsSize; ++i)
741static std::vector<Instruction*>
getSuccs(Instruction *i) {
742 BasicBlock *bb = i->getParent();
743 std::vector<Instruction*> res;
745 if (i==bb->getTerminator()) {
746 for (succ_iterator it = succ_begin(bb), ie = succ_end(bb); it != ie; ++it)
747 res.push_back(&*(it->begin()));
749 res.push_back(&*(++(i->getIterator())));
756 uint64_t minDistAtRA) {
758 if (minDistAtRA==0) {
767 if (distToReturn==0) {
769 }
else if (!minDistLocal) {
770 return distToReturn + minDistAtRA;
772 return std::min(minDistLocal, distToReturn + minDistAtRA);
779 const auto m = km->
module.get();
780 static bool init =
true;
790 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
791 fnIt != fn_ie; ++fnIt) {
792 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
793 bbIt != bb_ie; ++bbIt) {
794 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
796 Instruction *inst = &*it;
797 if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
798#if LLVM_VERSION_CODE >= LLVM_VERSION(8, 0)
799 const CallBase &cs = cast<CallBase>(*inst);
800 if (isa<InlineAsm>(cs.getCalledOperand())) {
802 const CallSite cs(inst);
803 if (isa<InlineAsm>(cs.getCalledValue())) {
808 std::vector<Function*>()));
823 for (calltargets_ty::iterator it =
callTargets.begin(),
825 for (std::vector<Function*>::iterator fit = it->second.begin(),
826 fie = it->second.end(); fit != fie; ++fit)
832 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
833 fnIt != fn_ie; ++fnIt) {
834 Function *fn = &*fnIt;
835 if (fnIt->isDeclaration()) {
836 if (fnIt->doesNotReturn()) {
846 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
847 bbIt != bb_ie; ++bbIt) {
848 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
850 Instruction *inst = &*it;
855 isa<ReturnInst>(inst)
869 Instruction *inst = *it;
870 unsigned bestThrough = 0;
872 if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
873 std::vector<Function*> &targets =
callTargets[inst];
874 for (std::vector<Function*>::iterator fnIt = targets.begin(),
875 ie = targets.end(); fnIt != ie; ++fnIt) {
879 if (bestThrough==0 || dist<bestThrough)
890 std::vector<Instruction*> succs =
getSuccs(*it);
891 for (std::vector<Instruction*>::iterator it2 = succs.begin(),
892 ie = succs.end(); it2 != ie; ++it2) {
896 uint64_t val = bestThrough + dist;
897 if (best==0 || val<best)
905 Function *f = inst->getParent()->getParent();
906 if (best != cur || (inst == &*(f->begin()->begin())
912 if (inst == &*(f->begin()->begin()))
922 for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
923 fnIt != fn_ie; ++fnIt) {
925 for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
926 bbIt != bb_ie; ++bbIt) {
927 for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end();
929 Instruction *inst = &*it;
945 for (std::vector<Instruction*>::iterator it =
instructions.begin(),
947 Instruction *inst = *it;
950 unsigned bestThrough = 0;
952 if (isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
953 std::vector<Function*> &targets =
callTargets[inst];
954 for (std::vector<Function*>::iterator fnIt = targets.begin(),
955 ie = targets.end(); fnIt != ie; ++fnIt) {
959 if (bestThrough==0 || dist<bestThrough)
963 if (!(*fnIt)->isDeclaration()) {
967 calleeDist = 1+calleeDist;
968 if (best==0 || calleeDist<best)
978 std::vector<Instruction*> succs =
getSuccs(inst);
979 for (std::vector<Instruction*>::iterator it2 = succs.begin(),
980 ie = succs.end(); it2 != ie; ++it2) {
984 uint64_t val = bestThrough + dist;
985 if (best==0 || val<best)
999 for (std::set<ExecutionState*>::iterator it =
executor.
states.begin(),
1002 uint64_t currentFrameMinDist = 0;
1003 for (ExecutionState::stack_ty::iterator sfIt = es->
stack.begin(),
1004 sf_ie = es->
stack.end(); sfIt != sf_ie; ++sfIt) {
1005 ExecutionState::stack_ty::iterator next = sfIt + 1;
1008 if (next==es->
stack.end()) {
1015 sfIt->minDistToUncoveredOnReturn = currentFrameMinDist;
static std::map< Function *, std::vector< Instruction * > > functionCallers
static calltargets_ty callTargets
static std::vector< Instruction * > getSuccs(Instruction *i)
static bool instructionIsCoverable(Instruction *i)
std::map< Instruction *, std::vector< Function * > > calltargets_ty
static std::map< Function *, unsigned > functionShortestPath
std::string sqlite3ErrToStringAndFree(const std::string &prefix, char *sqlite3ErrMsg)
#define LLVM_VERSION_CODE
#define LLVM_VERSION(major, minor)
CallPathNode * getCallPath(CallPathNode *parent, const llvm::Instruction *callSite, const llvm::Function *f)
void getSummaryStatistics(CallSiteSummaryTable &result)
StatisticRecord statistics
ExecutionState representing a path under exploration.
stack_ty stack
Stack representing the current instruction stream.
std::map< const std::string *, std::set< std::uint32_t > > coveredLines
Set containing which lines in which files are covered by this state.
bool coveredNew
Whether a new instruction was covered in this state.
std::uint32_t instsSinceCovNew
Counts how many instructions were executed since the last new instruction was covered.
KInstIterator pc
Pointer to instruction to be executed after the current instruction.
std::set< ExecutionState *, ExecutionStateIDCompare > states
InterpreterHandler * interpreterHandler
std::unique_ptr< KModule > kmodule
const FunctionInfo & getFunctionInfo(const llvm::Function &) const
const InstructionInfo & getInfo(const llvm::Instruction &) const
virtual std::string getOutputFilename(const std::string &filename)=0
virtual std::unique_ptr< llvm::raw_fd_ostream > openOutputFile(const std::string &filename)=0
std::unique_ptr< InstructionInfoTable > infos
std::set< llvm::Function * > escapingFunctions
std::vector< std::unique_ptr< KFunction > > functions
std::unique_ptr< llvm::Module > module
size_t getUsedDeterministicSize()
void setIndexedValue(const Statistic &s, unsigned index, uint64_t value)
Statistic & getStatistic(unsigned i)
int getStatisticID(const std::string &name) const
void setIndex(unsigned i)
void useIndexedStats(unsigned totalIndices)
uint64_t getIndexedValue(const Statistic &s, unsigned index) const
void incrementIndexedValue(const Statistic &s, unsigned index, uint64_t addend) const
void setContext(StatisticRecord *sr)
unsigned getNumStatistics()
uint64_t getValue(const Statistic &s) const
const std::string & getName() const
getName - Get the statistic name.
std::uint64_t getValue() const
getValue - Get the current primary statistic value.
const std::string & getShortName() const
std::uint32_t getID() const
getID - Get the unique statistic ID.
void updateStateStatistics(uint64_t addend)
static bool useStatistics()
CallPathManager callPathManager
std::string objectFilename
std::uint32_t statsCommitEvery
void markBranchVisited(ExecutionState *visitedTrue, ExecutionState *visitedFalse)
::sqlite3_stmt * transactionBeginStmt
bool updateMinDistToUncovered
void stepInstruction(ExecutionState &es)
time::Point startWallTime
void computeReachableUncovered()
::sqlite3_stmt * transactionEndStmt
std::uint32_t statsWriteCount
std::unique_ptr< llvm::raw_fd_ostream > istatsFile
time::Span elapsed()
Return duration since execution start.
void framePopped(ExecutionState &es)
StatsTracker(Executor &_executor, std::string _objectFilename, bool _updateMinDistToUncovered)
::sqlite3_stmt * insertStmt
void framePushed(ExecutionState &es, StackFrame *parentFrame)
void add(std::unique_ptr< Timer > timer)
Statistic minDistToReturn
Statistic queryCexCacheMisses
Statistic queryConstructs
Statistic instructionTime
Statistic queryCexCacheHits
Statistic coveredInstructions
Statistic uncoveredInstructions
Statistic instructionRealTime
Statistic minDistToUncovered
Span getUserTime()
Returns time spent by this process in user mode.
Point getWallTime()
Returns point in time using a monotonic steady clock.
size_t GetTotalMallocUsage()
Get total malloc usage in bytes.
uint64_t computeMinDistToUncovered(const KInstruction *ki, uint64_t minDistAtRA)
std::map< const llvm::Instruction *, std::map< const llvm::Function *, CallSiteInfo > > CallSiteSummaryTable
llvm::Function * getDirectCallTarget(const llvm::CallBase &cb, bool moduleIsFullyLinked)
bool userSearcherRequiresMD2U()
void klee_error(const char *msg,...) __attribute__((format(printf
void void void klee_warning(const char *msg,...) __attribute__((format(printf
StatisticManager * theStatisticManager
StatisticRecord statistics
FunctionInfo stores debug information for a KFunction.
unsigned line
Line number in source file.
const std::string & file
Source file name.
uint64_t assemblyLine
Line number in generated assembly.ll.
unsigned id
The function id.
InstructionInfo stores debug information for a KInstruction.
const std::string & file
Source file name.
unsigned assemblyLine
Line number in generated assembly.ll.
unsigned line
Line number in source file.
unsigned id
The instruction id.
llvm::Function * function
KInstruction ** instructions
const InstructionInfo * info
unsigned minDistToUncoveredOnReturn
CallPathNode * callPathNode