22#include "llvm/IR/Function.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/raw_ostream.h"
37cl::opt<bool> DebugLogStateMerge(
38 "debug-log-state-merge", cl::init(
false),
39 cl::desc(
"Debug information for underlying state merging (default=false)"),
45std::uint32_t ExecutionState::nextID = 1;
50 : caller(_caller), kf(_kf), callPathNode(0),
51 minDistToUncoveredOnReturn(0), varargs(0) {
58 callPathNode(s.callPathNode),
60 minDistToUncoveredOnReturn(s.minDistToUncoveredOnReturn),
81 cur_mergehandler->removeOpenState(
this);
91 incomingBBIndex(state.incomingBBIndex),
93 addressSpace(state.addressSpace),
94 constraints(state.constraints),
96 symPathOS(state.symPathOS),
97 coveredLines(state.coveredLines),
98 symbolics(state.symbolics),
99 cexPreferences(state.cexPreferences),
100 arrayNames(state.arrayNames),
101 openMergeStack(state.openMergeStack),
102 steppedInstructions(state.steppedInstructions),
103 instsSinceCovNew(state.instsSinceCovNew),
104 unwindingInformation(state.unwindingInformation
105 ? state.unwindingInformation->clone()
107 coveredNew(state.coveredNew),
108 forkDisabled(state.forkDisabled) {
110 cur_mergehandler->addOpenState(
this);
118 falseState->coveredNew =
false;
119 falseState->coveredLines.clear();
130 for (
const auto * memoryObject : sf.
allocas)
146 os <<
"MO" << it->first->id <<
":" << it->second.get();
147 for (++it; it!=ie; ++it)
148 os <<
", MO" << it->first->id <<
":" << it->second.get();
155 if (DebugLogStateMerge)
156 llvm::errs() <<
"-- attempting merge of A:" <<
this <<
" with B:" << &b
168 std::vector<StackFrame>::const_iterator itA =
stack.begin();
169 std::vector<StackFrame>::const_iterator itB = b.
stack.begin();
170 while (itA!=
stack.end() && itB!=b.
stack.end()) {
172 if (itA->caller!=itB->caller || itA->kf!=itB->kf)
184 std::set< ref<Expr> > commonConstraints, aSuffix, bSuffix;
185 std::set_intersection(aConstraints.begin(), aConstraints.end(),
186 bConstraints.begin(), bConstraints.end(),
187 std::inserter(commonConstraints, commonConstraints.begin()));
188 std::set_difference(aConstraints.begin(), aConstraints.end(),
189 commonConstraints.begin(), commonConstraints.end(),
190 std::inserter(aSuffix, aSuffix.end()));
191 std::set_difference(bConstraints.begin(), bConstraints.end(),
192 commonConstraints.begin(), commonConstraints.end(),
193 std::inserter(bSuffix, bSuffix.end()));
194 if (DebugLogStateMerge) {
195 llvm::errs() <<
"\tconstraint prefix: [";
196 for (std::set<
ref<Expr> >::iterator it = commonConstraints.begin(),
197 ie = commonConstraints.end();
199 llvm::errs() << *it <<
", ";
200 llvm::errs() <<
"]\n";
201 llvm::errs() <<
"\tA suffix: [";
202 for (std::set<
ref<Expr> >::iterator it = aSuffix.begin(),
205 llvm::errs() << *it <<
", ";
206 llvm::errs() <<
"]\n";
207 llvm::errs() <<
"\tB suffix: [";
208 for (std::set<
ref<Expr> >::iterator it = bSuffix.begin(),
211 llvm::errs() << *it <<
", ";
212 llvm::errs() <<
"]\n";
224 if (DebugLogStateMerge) {
225 llvm::errs() <<
"\tchecking object states\n";
230 std::set<const MemoryObject*> mutated;
235 for (; ai!=ae && bi!=be; ++ai, ++bi) {
236 if (ai->first != bi->first) {
237 if (DebugLogStateMerge) {
238 if (ai->first < bi->first) {
239 llvm::errs() <<
"\t\tB misses binding for: " << ai->first->id <<
"\n";
241 llvm::errs() <<
"\t\tA misses binding for: " << bi->first->id <<
"\n";
246 if (ai->second.get() != bi->second.get()) {
247 if (DebugLogStateMerge)
248 llvm::errs() <<
"\t\tmutated: " << ai->first->id <<
"\n";
249 mutated.insert(ai->first);
252 if (ai!=ae || bi!=be) {
253 if (DebugLogStateMerge)
254 llvm::errs() <<
"\t\tmappings differ\n";
262 for (std::set<
ref<Expr> >::iterator it = aSuffix.begin(),
263 ie = aSuffix.end(); it != ie; ++it)
264 inA = AndExpr::create(inA, *it);
265 for (std::set<
ref<Expr> >::iterator it = bSuffix.begin(),
266 ie = bSuffix.end(); it != ie; ++it)
267 inB = AndExpr::create(inB, *it);
273 std::vector<StackFrame>::iterator itA =
stack.begin();
274 std::vector<StackFrame>::const_iterator itB = b.
stack.begin();
275 for (; itA!=
stack.end(); ++itA, ++itB) {
290 for (std::set<const MemoryObject*>::iterator it = mutated.begin(),
291 ie = mutated.end(); it != ie; ++it) {
296 "objects mutated but not writable in merging state");
300 for (
unsigned i=0; i<mo->
size; i++) {
310 for (
const auto &constraint : commonConstraints)
320 for (ExecutionState::stack_ty::const_reverse_iterator
326 out <<
"\t#" << idx++;
327 std::stringstream AssStream;
328 AssStream << std::setw(8) << std::setfill(
'0') << ii.
assemblyLine;
329 out << AssStream.str();
330 out <<
" in " << f->getName().str() <<
" (";
333 for (Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end();
335 if (ai!=f->arg_begin()) out <<
", ";
337 out << ai->getName().str();
340 if (isa_and_nonnull<ConstantExpr>(value))
345 out <<
" at " << ii.
file <<
":" << ii.
line;
void unbindObject(const MemoryObject *mo)
Remove a binding from the address space.
const ObjectState * findObject(const MemoryObject *mo) const
Lookup a binding from a MemoryObject.
ObjectState * getWriteable(const MemoryObject *mo, const ObjectState *os)
Obtain an ObjectState suitable for writing.
static ref< ConstantExpr > alloc(const llvm::APInt &v)
Manages constraints, e.g. optimisation.
void addConstraint(const ref< Expr > &constraint)
constraint_iterator end() const
constraint_iterator begin() const
ExecutionState representing a path under exploration.
stack_ty stack
Stack representing the current instruction stream.
void addConstraint(ref< Expr > e)
void pushFrame(KInstIterator caller, KFunction *kf)
void addSymbolic(const MemoryObject *mo, const Array *array)
ConstraintSet constraints
Constraints collected so far.
std::vector< ref< MergeHandler > > openMergeStack
The objects handling the klee_open_merge calls this state ran through.
bool merge(const ExecutionState &b)
AddressSpace addressSpace
Address space used by this state (e.g. Global and Heap)
std::vector< std::pair< ref< const MemoryObject >, const Array * > > symbolics
Ordered list of symbolics: used to generate test cases.
void dumpStack(llvm::raw_ostream &out) const
void addCexPreference(const ref< Expr > &cond)
ExecutionState(const ExecutionState &state)
KInstIterator prevPC
Pointer to instruction which is currently executed.
std::uint32_t depth
Exploration depth, i.e., number of times KLEE branched for this state.
ExecutionState * branch()
ImmutableSet< ref< Expr > > cexPreferences
A set of boolean expressions the user has requested be true of a counterexample.
KInstIterator pc
Pointer to instruction to be executed after the current instruction.
unsigned size
size in bytes
ref< Expr > read8(unsigned offset) const
void write(unsigned offset, ref< Expr > value)
static ref< Expr > create(ref< Expr > c, ref< Expr > t, ref< Expr > f)
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const MemoryMap &mm)
llvm::cl::OptionCategory MergeCat
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 getArgRegister(unsigned index)
llvm::Function * function
const InstructionInfo * info
std::vector< const MemoryObject * > allocas
StackFrame(KInstIterator caller, KFunction *kf)