void SpecialFunctionHandler::handleStrcat(ExecutionState &state, KInstruction *target, std::vector<ref<Expr> > &arguments) { ObjectPair dst_op; ref<Expr> addressExpr; addressExpr = executor.toUnique(state, arguments[0]); ref<ConstantExpr> address = cast<ConstantExpr>(addressExpr); if (!state.addressSpace.resolveOne(address, dst_op)) assert(0 && "XXX out of bounds / multiple resolution unhandled"); const MemoryObject *dst_mo = dst_op.first; const MemoryObject *dst_mo_len = dst_mo->length; const ObjectState *dst_os_len = state.addressSpace.findObject(dst_mo_len); ref<Expr> dst_len_expr = dst_os_len->read(0, 32); ObjectPair src_op; addressExpr = executor.toUnique(state, arguments[1]); address = cast<ConstantExpr>(addressExpr); if (!state.addressSpace.resolveOne(address, src_op)) assert(0 && "XXX out of bounds / multiple resolution unhandled"); const MemoryObject *src_mo = src_op.first; const MemoryObject *src_mo_len = src_mo->length; const ObjectState *src_os_len = state.addressSpace.findObject(src_mo_len); ref<Expr> src_len_expr = src_os_len->read(0, 32); //std::cerr << "klee_strcat called, dst_len_expr = " << dst_len_expr << "; src_len_expr = " << src_len_expr << "\n"; ObjectState *wos = state.addressSpace.getWriteable(dst_mo_len, dst_os_len); ref<Expr> total_len_expr = AddExpr::create(dst_len_expr, src_len_expr); //std::cerr << "total_len_expr = " << total_len_expr << "\n"; wos->write(0, total_len_expr); /* this proves that now, dst_mo_len's os_state has been modified dst_os_len = state.addressSpace.findObject(dst_mo_len); std::cerr << "dol = " << dst_os_len->read(0,32) << "\n"; */ }
bool ExecutionState::merge(const ExecutionState &b) { if (DebugLogStateMerge) llvm::errs() << "-- attempting merge of A:" << this << " with B:" << &b << "--\n"; if (pc != b.pc) return false; // XXX is it even possible for these to differ? does it matter? probably // implies difference in object states? if (symbolics!=b.symbolics) return false; { std::vector<StackFrame>::const_iterator itA = stack.begin(); std::vector<StackFrame>::const_iterator itB = b.stack.begin(); while (itA!=stack.end() && itB!=b.stack.end()) { // XXX vaargs? if (itA->caller!=itB->caller || itA->kf!=itB->kf) return false; ++itA; ++itB; } if (itA!=stack.end() || itB!=b.stack.end()) return false; } std::set< ref<Expr> > aConstraints(constraints.begin(), constraints.end()); std::set< ref<Expr> > bConstraints(b.constraints.begin(), b.constraints.end()); std::set< ref<Expr> > commonConstraints, aSuffix, bSuffix; std::set_intersection(aConstraints.begin(), aConstraints.end(), bConstraints.begin(), bConstraints.end(), std::inserter(commonConstraints, commonConstraints.begin())); std::set_difference(aConstraints.begin(), aConstraints.end(), commonConstraints.begin(), commonConstraints.end(), std::inserter(aSuffix, aSuffix.end())); std::set_difference(bConstraints.begin(), bConstraints.end(), commonConstraints.begin(), commonConstraints.end(), std::inserter(bSuffix, bSuffix.end())); if (DebugLogStateMerge) { llvm::errs() << "\tconstraint prefix: ["; for (std::set<ref<Expr> >::iterator it = commonConstraints.begin(), ie = commonConstraints.end(); it != ie; ++it) llvm::errs() << *it << ", "; llvm::errs() << "]\n"; llvm::errs() << "\tA suffix: ["; for (std::set<ref<Expr> >::iterator it = aSuffix.begin(), ie = aSuffix.end(); it != ie; ++it) llvm::errs() << *it << ", "; llvm::errs() << "]\n"; llvm::errs() << "\tB suffix: ["; for (std::set<ref<Expr> >::iterator it = bSuffix.begin(), ie = bSuffix.end(); it != ie; ++it) llvm::errs() << *it << ", "; llvm::errs() << "]\n"; } // We cannot merge if addresses would resolve differently in the // states. This means: // // 1. Any objects created since the branch in either object must // have been free'd. // // 2. We cannot have free'd any pre-existing object in one state // and not the other if (DebugLogStateMerge) { llvm::errs() << "\tchecking object states\n"; llvm::errs() << "A: " << addressSpace.objects << "\n"; llvm::errs() << "B: " << b.addressSpace.objects << "\n"; } std::set<const MemoryObject*> mutated; MemoryMap::iterator ai = addressSpace.objects.begin(); MemoryMap::iterator bi = b.addressSpace.objects.begin(); MemoryMap::iterator ae = addressSpace.objects.end(); MemoryMap::iterator be = b.addressSpace.objects.end(); for (; ai!=ae && bi!=be; ++ai, ++bi) { if (ai->first != bi->first) { if (DebugLogStateMerge) { if (ai->first < bi->first) { llvm::errs() << "\t\tB misses binding for: " << ai->first->id << "\n"; } else { llvm::errs() << "\t\tA misses binding for: " << bi->first->id << "\n"; } } return false; } if (ai->second != bi->second) { if (DebugLogStateMerge) llvm::errs() << "\t\tmutated: " << ai->first->id << "\n"; mutated.insert(ai->first); } } if (ai!=ae || bi!=be) { if (DebugLogStateMerge) llvm::errs() << "\t\tmappings differ\n"; return false; } // merge stack ref<Expr> inA = ConstantExpr::alloc(1, Expr::Bool); ref<Expr> inB = ConstantExpr::alloc(1, Expr::Bool); for (std::set< ref<Expr> >::iterator it = aSuffix.begin(), ie = aSuffix.end(); it != ie; ++it) inA = AndExpr::create(inA, *it); for (std::set< ref<Expr> >::iterator it = bSuffix.begin(), ie = bSuffix.end(); it != ie; ++it) inB = AndExpr::create(inB, *it); // XXX should we have a preference as to which predicate to use? // it seems like it can make a difference, even though logically // they must contradict each other and so inA => !inB std::vector<StackFrame>::iterator itA = stack.begin(); std::vector<StackFrame>::const_iterator itB = b.stack.begin(); for (; itA!=stack.end(); ++itA, ++itB) { StackFrame &af = *itA; const StackFrame &bf = *itB; for (unsigned i=0; i<af.kf->numRegisters; i++) { ref<Expr> &av = af.locals[i].value; const ref<Expr> &bv = bf.locals[i].value; if (av.isNull() || bv.isNull()) { // if one is null then by implication (we are at same pc) // we cannot reuse this local, so just ignore } else { av = SelectExpr::create(inA, av, bv); } } } for (std::set<const MemoryObject*>::iterator it = mutated.begin(), ie = mutated.end(); it != ie; ++it) { const MemoryObject *mo = *it; const ObjectState *os = addressSpace.findObject(mo); const ObjectState *otherOS = b.addressSpace.findObject(mo); assert(os && !os->readOnly && "objects mutated but not writable in merging state"); assert(otherOS); ObjectState *wos = addressSpace.getWriteable(mo, os); for (unsigned i=0; i<mo->size; i++) { ref<Expr> av = wos->read8(i); ref<Expr> bv = otherOS->read8(i); wos->write(i, SelectExpr::create(inA, av, bv)); } } constraints = ConstraintManager(); for (std::set< ref<Expr> >::iterator it = commonConstraints.begin(), ie = commonConstraints.end(); it != ie; ++it) constraints.addConstraint(*it); constraints.addConstraint(OrExpr::create(inA, inB)); return true; }
void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, std::vector< ref<Expr> > &arguments) { fireControlFlowEvent(&state, ::cloud9::worker::CALL); if (f && DebugCallHistory) { unsigned depth = state.stack().size(); LOG(INFO) << "Call[" << &state << "]: " << std::string(depth, ' ') << f->getName().str(); } Instruction *i = NULL; if (ki) i = ki->inst; if (ki && f && f->isDeclaration()) { switch(f->getIntrinsicID()) { case Intrinsic::not_intrinsic: // state may be destroyed by this call, cannot touch callExternalFunction(state, ki, f, arguments); break; // va_arg is handled by caller and intrinsic lowering, see comment for // ExecutionState::varargs case Intrinsic::vastart: { StackFrame &sf = state.stack().back(); assert(sf.varargs && "vastart called in function with no vararg object"); // FIXME: This is really specific to the architecture, not the pointer // size. This happens to work fir x86-32 and x86-64, however. Expr::Width WordSize = Context::get().getPointerWidth(); if (WordSize == Expr::Int32) { executeMemoryOperation(state, true, arguments[0], sf.varargs->getBaseExpr(), 0); } else { assert(WordSize == Expr::Int64 && "Unknown word size!"); // X86-64 has quite complicated calling convention. However, // instead of implementing it, we can do a simple hack: just // make a function believe that all varargs are on stack. executeMemoryOperation(state, true, arguments[0], ConstantExpr::create(48, 32), 0); // gp_offset executeMemoryOperation(state, true, AddExpr::create(arguments[0], ConstantExpr::create(4, 64)), ConstantExpr::create(304, 32), 0); // fp_offset executeMemoryOperation(state, true, AddExpr::create(arguments[0], ConstantExpr::create(8, 64)), sf.varargs->getBaseExpr(), 0); // overflow_arg_area executeMemoryOperation(state, true, AddExpr::create(arguments[0], ConstantExpr::create(16, 64)), ConstantExpr::create(0, 64), 0); // reg_save_area } break; } case Intrinsic::vaend: // va_end is a noop for the interpreter. // // FIXME: We should validate that the target didn't do something bad // with vaeend, however (like call it twice). break; case Intrinsic::vacopy: // va_copy should have been lowered. // // FIXME: It would be nice to check for errors in the usage of this as // well. default: LOG(FATAL) << "Unknown intrinsic: " << f->getName().data(); } if (InvokeInst *ii = dyn_cast<InvokeInst>(i)) transferToBasicBlock(ii->getNormalDest(), i->getParent(), state); } else { // FIXME: I'm not really happy about this reliance on prevPC but it is ok, I // guess. This just done to avoid having to pass KInstIterator everywhere // instead of the actual instruction, since we can't make a KInstIterator // from just an instruction (unlike LLVM). KFunction *kf = kmodule->functionMap[f]; state.pushFrame(state.prevPC(), kf); state.pc() = kf->instructions; if (statsTracker) statsTracker->framePushed(state, &state.stack()[state.stack().size()-2]); //XXX TODO fix this ugly stuff // TODO: support "byval" parameter attribute // TODO: support zeroext, signext, sret attributes unsigned callingArgs = arguments.size(); unsigned funcArgs = f->arg_size(); if (!f->isVarArg()) { if (callingArgs > funcArgs) { LOG(WARNING) << "Calling " << f->getName().data() << " with extra arguments."; } else if (callingArgs < funcArgs) { terminateStateOnError(state, "calling function with too few arguments", "user.err"); return; } } else { if (callingArgs < funcArgs) { terminateStateOnError(state, "calling function with too few arguments", "user.err"); return; } StackFrame &sf = state.stack().back(); unsigned size = 0; for (unsigned i = funcArgs; i < callingArgs; i++) { // FIXME: This is really specific to the architecture, not the pointer // size. This happens to work fir x86-32 and x86-64, however. Expr::Width WordSize = Context::get().getPointerWidth(); if (WordSize == Expr::Int32) { size += Expr::getMinBytesForWidth(arguments[i]->getWidth()); } else { size += llvm::RoundUpToAlignment(arguments[i]->getWidth(), WordSize) / 8; } } MemoryObject *mo = sf.varargs = memory->allocate(&state, size, true, false, state.prevPC()->inst); if (!mo) { terminateStateOnExecError(state, "out of memory (varargs)"); return; } ObjectState *os = bindObjectInState(state, mo, true); unsigned offset = 0; for (unsigned i = funcArgs; i < callingArgs; i++) { // FIXME: This is really specific to the architecture, not the pointer // size. This happens to work fir x86-32 and x86-64, however. Expr::Width WordSize = Context::get().getPointerWidth(); if (WordSize == Expr::Int32) { os->write(offset, arguments[i]); offset += Expr::getMinBytesForWidth(arguments[i]->getWidth()); } else { assert(WordSize == Expr::Int64 && "Unknown word size!"); os->write(offset, arguments[i]); offset += llvm::RoundUpToAlignment(arguments[i]->getWidth(), WordSize) / 8; } } } unsigned numFormals = f->arg_size(); for (unsigned i=0; i<numFormals; ++i) bindArgument(kf, i, state, arguments[i]); } }