SymbolicExpr::VisitAction preVisit(const SymbolicExpr::Ptr &node) { if (!seen.insert(getRawPointer(node)).second) return SymbolicExpr::TRUNCATE; // already processed this subexpression if (SymbolicExpr::LeafPtr leaf = node->isLeafNode()) { if (leaf->isVariable()) { if (defns->find(leaf->nameId()) == defns->end()) { defns->insert(leaf->nameId()); yices_type bvtype = yices_mk_bitvector_type(self->context, leaf->nBits()); ASSERT_not_null(bvtype); std::string name = "v" + StringUtility::numberToString(leaf->nameId()); yices_var_decl vdecl __attribute__((unused)) = yices_mk_var_decl(self->context, name.c_str(), bvtype); ASSERT_not_null(vdecl); } } else if (leaf->isMemory()) { if (defns->find(leaf->nameId()) == defns->end()) { defns->insert(leaf->nameId()); yices_type domain = yices_mk_bitvector_type(self->context, leaf->domainWidth()); yices_type range = yices_mk_bitvector_type(self->context, leaf->nBits()); yices_type ftype = yices_mk_function_type(self->context, &domain, 1, range); ASSERT_not_null(ftype); std::string name = "m" + StringUtility::numberToString(leaf->nameId()); yices_var_decl vdecl __attribute__((unused)) = yices_mk_var_decl(self->context, name.c_str(), ftype); ASSERT_not_null(vdecl); } } } return SymbolicExpr::CONTINUE; }
void appendExpression(SgAsmExprListExp *exprList, SgAsmExpression *expr) { ASSERT_not_null(exprList); ASSERT_not_null(expr); expr->set_parent(exprList); exprList->get_expressions().push_back(expr); }
void RiscOperators::startInstruction(SgAsmInstruction *insn) { ASSERT_not_null(currentState()); ASSERT_not_null(currentState()->memoryState()); BaseSemantics::MemoryStatePtr mem = currentState()->memoryState(); if (MemoryListStatePtr ml = boost::dynamic_pointer_cast<MemoryListState>(mem)) { ml->addressesRead().clear(); } else if (MemoryMapStatePtr mm = boost::dynamic_pointer_cast<MemoryMapState>(mem)) { mm->addressesRead().clear(); } SymbolicSemantics::RiscOperators::startInstruction(insn); }
/* Class method to register a new disassembler subclass. Thread safe. */ void Disassembler::register_subclass(Disassembler *factory) { boost::lock_guard<boost::mutex> lock(class_mutex); ASSERT_not_null(factory); disassemblers.push_back(factory); }
RiscOperatorsPtr RiscOperators::promote(const BaseSemantics::RiscOperatorsPtr &ops) { RiscOperatorsPtr retval = boost::dynamic_pointer_cast<RiscOperators>(ops); ASSERT_not_null(retval); return retval; }
// Output for "set" operator. (set a b c) gets translated to the symbolic expression (ite v1 a (ite v1 b c)), which // in turn gets translated to Yices output. void YicesSolver::out_set(std::ostream &o, const SymbolicExpr::InteriorPtr &in) { ASSERT_not_null(in); ASSERT_require(in->getOperator() == SymbolicExpr::OP_SET); ASSERT_require(in->nChildren() >= 2); SymbolicExpr::Ptr ite = SymbolicExpr::setToIte(in); out_expr(o, ite); }
/** Emit type name for term. */ std::string YicesSolver::get_typename(const SymbolicExpr::Ptr &expr) { ASSERT_not_null(expr); if (expr->isScalar()) return "(bitvector " + StringUtility::numberToString(expr->nBits()) + ")"; return ("(-> (bitvector " + StringUtility::numberToString(expr->domainWidth()) + ")" " (bitvector " + StringUtility::numberToString(expr->nBits()) + "))"); }
NoOperation::NoOperation(Disassembler *disassembler) { normalizer_ = StateNormalizer::instance(); if (disassembler) { const RegisterDictionary *registerDictionary = disassembler->get_registers(); ASSERT_not_null(registerDictionary); size_t addrWidth = disassembler->instructionPointerRegister().get_nbits(); SMTSolver *solver = NULL; SymbolicSemantics::RiscOperatorsPtr ops = SymbolicSemantics::RiscOperators::instance(registerDictionary, solver); ops->computingDefiners(SymbolicSemantics::TRACK_NO_DEFINERS); ops->computingMemoryWriters(SymbolicSemantics::TRACK_LATEST_WRITER); // necessary to erase non-written memory BaseSemantics::MemoryCellListPtr mstate = BaseSemantics::MemoryCellList::promote(ops->currentState()->memoryState()); ASSERT_not_null(mstate); mstate->occlusionsErased(true); cpu_ = disassembler->dispatcher()->create(ops, addrWidth, registerDictionary); } }
void RiscOperators::startInstruction(SgAsmInstruction *insn) { ASSERT_not_null(partitioner_); Super::startInstruction(insn); if (mlog[DEBUG]) { SymbolicSemantics::Formatter fmt = symbolicFormat(" "); mlog[DEBUG] <<" +-------------------------------------------------\n" <<" | " <<unparseInstructionWithAddress(insn) <<"\n" <<" +-------------------------------------------------\n" <<" state before instruction:\n" <<(*currentState() + fmt); } }
size_t RiscOperators::add_subdomain(const BaseSemantics::RiscOperatorsPtr &subdomain, const std::string &name, bool activate) { ASSERT_not_null(subdomain); size_t idx = subdomains.size(); subdomains.push_back(subdomain); active.push_back(activate); if (idx>=formatter.subdomain_names.size()) formatter.subdomain_names.resize(idx+1, ""); formatter.subdomain_names[idx] = name; SValue::promote(protoval())->set_subvalue(idx, subdomain->protoval()); return idx; }
BaseSemantics::StatePtr NoOperation::initialState(SgAsmInstruction *insn) const { ASSERT_not_null(insn); ASSERT_not_null(cpu_); BaseSemantics::StatePtr state; if (normalizer_) { state = normalizer_->initialState(cpu_, insn); } else { state = cpu_->currentState()->clone(); state->clear(); RegisterDescriptor IP = cpu_->instructionPointerRegister(); state->writeRegister(IP, cpu_->number_(IP.get_nbits(), insn->get_address()), cpu_->get_operators().get()); } // Set the stack pointer to a concrete value if (initialSp_) { const RegisterDescriptor regSp = cpu_->stackPointerRegister(); BaseSemantics::RiscOperatorsPtr ops = cpu_->get_operators(); state->writeRegister(regSp, ops->number_(regSp.get_nbits(), *initialSp_), ops.get()); } return state; }
/** Traverse an expression and produce Yices "define" statements for variables. */ void YicesSolver::out_define(std::ostream &o, const std::vector<SymbolicExpr::Ptr> &exprs, Definitions *defns) { ASSERT_not_null(defns); struct T1: SymbolicExpr::Visitor { typedef std::set<const SymbolicExpr::Node*> SeenNodes; SeenNodes seen; std::ostream &o; Definitions *defns; T1(std::ostream &o, Definitions *defns) : o(o), defns(defns) {} SymbolicExpr::VisitAction preVisit(const SymbolicExpr::Ptr &node) { if (!seen.insert(getRawPointer(node)).second) return SymbolicExpr::TRUNCATE; // already processed this subexpression if (SymbolicExpr::LeafPtr leaf = node->isLeafNode()) { if (leaf->isVariable()) { if (defns->find(leaf->nameId())==defns->end()) { defns->insert(leaf->nameId()); o <<"\n"; if (!leaf->comment().empty()) o <<StringUtility::prefixLines(leaf->comment(), "; ") <<"\n"; o <<"(define v" <<leaf->nameId() <<"::" <<get_typename(leaf) <<")\n"; } } else if (leaf->isMemory()) { if (defns->find(leaf->nameId())==defns->end()) { defns->insert(leaf->nameId()); o <<"\n"; if (!leaf->comment().empty()) o <<StringUtility::prefixLines(leaf->comment(), "; ") <<"\n"; o <<"(define m" <<leaf->nameId() <<"::" <<get_typename(leaf) <<")\n"; } } } return SymbolicExpr::CONTINUE; } SymbolicExpr::VisitAction postVisit(const SymbolicExpr::Ptr&) { return SymbolicExpr::CONTINUE; } } t1(o, defns); BOOST_FOREACH (const SymbolicExpr::Ptr &expr, exprs) expr->depthFirstTraversal(t1); }
SgAsmInstruction* InstructionProvider::operator[](rose_addr_t va) const { SgAsmInstruction *insn = NULL; if (!insnMap_.getOptional(va).assignTo(insn)) { if (useDisassembler_ && memMap_.at(va).require(MemoryMap::EXECUTABLE).exists()) { try { insn = disassembler_->disassembleOne(&memMap_, va); } catch (const Disassembler::Exception &e) { insn = disassembler_->make_unknown_instruction(e); ASSERT_not_null(insn); uint8_t byte; if (1==memMap_.at(va).limit(1).require(MemoryMap::EXECUTABLE).read(&byte).size()) insn->set_raw_bytes(SgUnsignedCharList(1, byte)); ASSERT_require(insn->get_address()==va); ASSERT_require(insn->get_size()==1); } } insnMap_.insert(va, insn); } return insn; }
RiscOperatorsPtr RiscOperators::instance(const Partitioner2::Partitioner *partitioner, const RegisterDictionary *regdict, const SmtSolver::Ptr &solver) { BaseSemantics::SValuePtr protoval = SValue::instance(); BaseSemantics::RegisterStatePtr registers = RegisterState::instance(protoval, regdict); BaseSemantics::MemoryStatePtr memory; switch (settings.searchMode) { case SEARCH_MULTI: // If we're sending multiple paths at a time to the SMT solver then we need to provide the SMT solver with // detailed information about how memory is affected on those different paths. memory = BaseSemantics::SymbolicMemory::instance(protoval, protoval); break; case SEARCH_SINGLE_DFS: case SEARCH_SINGLE_BFS: // We can perform memory-related operations and simplifications inside ROSE, which results in more but smaller // expressions being sent to the SMT solver. memory = SymbolicSemantics::MemoryState::instance(protoval, protoval); break; } ASSERT_not_null(memory); BaseSemantics::StatePtr state = State::instance(registers, memory); return RiscOperatorsPtr(new RiscOperators(partitioner, state, solver)); }
void InstructionProvider::insert(SgAsmInstruction *insn) { ASSERT_not_null(insn); insnMap_.insert(insn->get_address(), insn); }
SgAsmFloatValueExpression* buildValueFloat(const Sawyer::Container::BitVector &bv, SgAsmType *type) { ASSERT_not_null(type); ASSERT_require(bv.size() == type->get_nBits()); return new SgAsmFloatValueExpression(bv, type); }
SgAsmFloatValueExpression* buildValueFloat(double x, SgAsmType *type) { ASSERT_not_null(type); return new SgAsmFloatValueExpression(x, type); }
/** Output for one expression. */ void YicesSolver::out_expr(std::ostream &o, const SymbolicExpr::Ptr &tn) { SymbolicExpr::LeafPtr ln = tn->isLeafNode(); SymbolicExpr::InteriorPtr in = tn->isInteriorNode(); std::string subExprName; if (termNames.getOptional(tn).assignTo(subExprName)) { o <<subExprName; } else if (ln) { if (ln->isNumber()) { if (ln->nBits() <= 64) { o <<"(mk-bv " <<ln->nBits() <<" " <<ln->toInt() <<")"; } else { o <<"0b" <<ln->bits().toBinary(); } } else if (ln->isMemory()) { o <<"m" <<ln->nameId(); } else { ASSERT_require(ln->isVariable()); o <<"v" <<ln->nameId(); } } else { ASSERT_not_null(in); switch (in->getOperator()) { case SymbolicExpr::OP_ADD: out_la(o, "bv-add", in, false); break; case SymbolicExpr::OP_AND: out_la(o, "and", in, true); break; case SymbolicExpr::OP_ASR: out_asr(o, in); break; case SymbolicExpr::OP_BV_AND: out_la(o, "bv-and", in, true); break; case SymbolicExpr::OP_BV_OR: out_la(o, "bv-or", in, false); break; case SymbolicExpr::OP_BV_XOR: out_la(o, "bv-xor", in, false); break; case SymbolicExpr::OP_EQ: out_binary(o, "=", in); break; case SymbolicExpr::OP_CONCAT: out_la(o, "bv-concat", in); break; case SymbolicExpr::OP_EXTRACT: out_extract(o, in); break; case SymbolicExpr::OP_INVERT: out_unary(o, "bv-not", in); break; case SymbolicExpr::OP_ITE: out_ite(o, in); break; case SymbolicExpr::OP_LSSB: throw Exception("OP_LSSB not implemented"); case SymbolicExpr::OP_MSSB: throw Exception("OP_MSSB not implemented"); case SymbolicExpr::OP_NE: out_binary(o, "/=", in); break; case SymbolicExpr::OP_NEGATE: out_unary(o, "bv-neg", in); break; case SymbolicExpr::OP_NOOP: o<<"0b1"; break; case SymbolicExpr::OP_OR: out_la(o, "or", in, false); break; case SymbolicExpr::OP_READ: out_read(o, in); break; case SymbolicExpr::OP_ROL: throw Exception("OP_ROL not implemented"); case SymbolicExpr::OP_ROR: throw Exception("OP_ROR not implemented"); case SymbolicExpr::OP_SDIV: throw Exception("OP_SDIV not implemented"); case SymbolicExpr::OP_SET: out_set(o, in); break; case SymbolicExpr::OP_SEXTEND: out_sext(o, in); break; case SymbolicExpr::OP_SLT: out_binary(o, "bv-slt", in); break; case SymbolicExpr::OP_SLE: out_binary(o, "bv-sle", in); break; case SymbolicExpr::OP_SHL0: out_shift(o, "bv-shift-left", in, false); break; case SymbolicExpr::OP_SHL1: out_shift(o, "bv-shift-left", in, true); break; case SymbolicExpr::OP_SHR0: out_shift(o, "bv-shift-right", in, false); break; case SymbolicExpr::OP_SHR1: out_shift(o, "bv-shift-right", in, true); break; case SymbolicExpr::OP_SGE: out_binary(o, "bv-sge", in); break; case SymbolicExpr::OP_SGT: out_binary(o, "bv-sgt", in); break; case SymbolicExpr::OP_SMOD: throw Exception("OP_SMOD not implemented"); case SymbolicExpr::OP_SMUL: out_mult(o, in); break; case SymbolicExpr::OP_UDIV: throw Exception("OP_UDIV not implemented"); case SymbolicExpr::OP_UEXTEND: out_uext(o, in); break; case SymbolicExpr::OP_UGE: out_binary(o, "bv-ge", in); break; case SymbolicExpr::OP_UGT: out_binary(o, "bv-gt", in); break; case SymbolicExpr::OP_ULE: out_binary(o, "bv-le", in); break; case SymbolicExpr::OP_ULT: out_binary(o, "bv-lt", in); break; case SymbolicExpr::OP_UMOD: throw Exception("OP_UMOD not implemented"); case SymbolicExpr::OP_UMUL: out_mult(o, in); break; case SymbolicExpr::OP_WRITE: out_write(o, in); break; case SymbolicExpr::OP_ZEROP: out_zerop(o, in); break; } } }