void RiscOperators::writeRegister(RegisterDescriptor reg, const BaseSemantics::SValuePtr &value) { SymbolicExpr::Ptr expr = SValue::promote(value)->get_expression(); if (expr->isLeafNode()) { std::string comment = commentForVariable(reg, "write"); State::promote(currentState())->varComment(expr->isLeafNode()->toString(), comment); } Super::writeRegister(reg, value); }
BaseSemantics::SValuePtr RiscOperators::readRegister(RegisterDescriptor reg, const BaseSemantics::SValuePtr &dflt) { SValuePtr retval = SValue::promote(Super::readRegister(reg, dflt)); SymbolicExpr::Ptr expr = retval->get_expression(); if (expr->isLeafNode()) { std::string comment = commentForVariable(reg, "read"); State::promote(currentState())->varComment(expr->isLeafNode()->toString(), comment); } return retval; }
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; }
/** Output a decimal number. */ void YicesSolver::out_number(std::ostream &o, const SymbolicExpr::Ptr &tn) { SymbolicExpr::LeafPtr ln = tn->isLeafNode(); ASSERT_require(ln && ln->isNumber()); o <<ln->toInt(); }
/** Read memory. * * If multi-path is enabled, then return a new memory expression that describes the process of reading a value from the * specified address; otherwise, actually read the value and return it. In any case, record some information about the * address that's being read if we've never seen it before. */ BaseSemantics::SValuePtr RiscOperators::readMemory(RegisterDescriptor segreg, const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &dflt_, const BaseSemantics::SValuePtr &cond) { BaseSemantics::SValuePtr dflt = dflt_; const size_t nBytes = dflt->get_width() / 8; if (cond->is_number() && !cond->get_number()) return dflt_; // If we know the address and that memory exists, then read the memory to obtain the default value. uint8_t buf[8]; if (addr->is_number() && nBytes < sizeof(buf) && nBytes == partitioner_->memoryMap()->at(addr->get_number()).limit(nBytes).read(buf).size()) { // FIXME[Robb P. Matzke 2015-05-25]: assuming little endian uint64_t value = 0; for (size_t i=0; i<nBytes; ++i) value |= (uint64_t)buf[i] << (8*i); dflt = number_(dflt->get_width(), value); } // Read from the symbolic state, and update the state with the default from real memory if known. BaseSemantics::SValuePtr retval = Super::readMemory(segreg, addr, dflt, cond); if (!currentInstruction()) return retval; // not called from dispatcher on behalf of an instruction // Save a description of the variable SymbolicExpr::Ptr valExpr = SValue::promote(retval)->get_expression(); if (valExpr->isLeafNode() && valExpr->isLeafNode()->isVariable()) { std::string comment = commentForVariable(addr, "read"); State::promote(currentState())->varComment(valExpr->isLeafNode()->toString(), comment); } // Save a description for its addresses for (size_t i=0; i<nBytes; ++i) { SValuePtr va = SValue::promote(add(addr, number_(addr->get_width(), i))); if (va->get_expression()->isLeafNode()) { std::string comment = commentForVariable(addr, "read", i, nBytes); State::promote(currentState())->varComment(va->get_expression()->isLeafNode()->toString(), comment); } } return retval; }
/** Write value to memory. * * If multi-path is enabled, then return a new memory expression that updates memory with a new address/value pair; * otherwise update the memory directly. In any case, record some information about the address that was written if we've * never seen it before. */ void RiscOperators::writeMemory(RegisterDescriptor segreg, const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &value, const BaseSemantics::SValuePtr &cond) { if (cond->is_number() && !cond->get_number()) return; Super::writeMemory(segreg, addr, value, cond); // Save a description of the variable SymbolicExpr::Ptr valExpr = SValue::promote(value)->get_expression(); if (valExpr->isLeafNode() && valExpr->isLeafNode()->isVariable()) { std::string comment = commentForVariable(addr, "write"); State::promote(currentState())->varComment(valExpr->isLeafNode()->toString(), comment); } // Save a description for its addresses size_t nBytes = value->get_width() / 8; for (size_t i=0; i<nBytes; ++i) { SValuePtr va = SValue::promote(add(addr, number_(addr->get_width(), i))); if (va->get_expression()->isLeafNode()) { std::string comment = commentForVariable(addr, "read", i, nBytes); State::promote(currentState())->varComment(va->get_expression()->isLeafNode()->toString(), comment); } } }
std::string RiscOperators::commentForVariable(const BaseSemantics::SValuePtr &addr, const std::string &accessMode, size_t byteNumber, size_t nBytes) const { std::string varComment = "first " + accessMode + " at "; if (pathInsnIndex_ != (size_t)(-1)) varComment += "path position #" + StringUtility::numberToString(pathInsnIndex_) + ", "; varComment += "instruction " + unparseInstructionWithAddress(currentInstruction()); // Sometimes we can save useful information about the address. if (nBytes != 1) { SymbolicExpr::Ptr addrExpr = SValue::promote(addr)->get_expression(); if (SymbolicExpr::LeafPtr addrLeaf = addrExpr->isLeafNode()) { if (addrLeaf->isNumber()) { varComment += "\n"; if (nBytes > 1) { varComment += StringUtility::numberToString(byteNumber) + " of " + StringUtility::numberToString(nBytes) + " bytes starting "; } varComment += "at address " + addrLeaf->toString(); } } else if (SymbolicExpr::InteriorPtr addrINode = addrExpr->isInteriorNode()) { if (addrINode->getOperator() == SymbolicExpr::OP_ADD && addrINode->nChildren() == 2 && addrINode->child(0)->isLeafNode() && addrINode->child(0)->isLeafNode()->isVariable() && addrINode->child(1)->isLeafNode() && addrINode->child(1)->isLeafNode()->isNumber()) { SymbolicExpr::LeafPtr base = addrINode->child(0)->isLeafNode(); SymbolicExpr::LeafPtr offset = addrINode->child(1)->isLeafNode(); varComment += "\n"; if (nBytes > 1) { varComment += StringUtility::numberToString(byteNumber) + " of " + StringUtility::numberToString(nBytes) + " bytes starting "; } varComment += "at address "; if (base->comment().empty()) { varComment = base->toString(); } else { varComment += base->comment(); } Sawyer::Container::BitVector tmp = offset->bits(); if (tmp.get(tmp.size()-1)) { varComment += " - 0x" + tmp.negate().toHex(); } else { varComment += " + 0x" + tmp.toHex(); } } } } return varComment; }
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() || leaf->isMemory()) && !leaf->comment().empty()) { if (!commented) { o <<"\n" <<";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n" <<"; Variable comments\n" <<";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"; commented = true; } o <<"\n; " <<leaf->toString() <<": " <<StringUtility::prefixLines(leaf->comment(), "; ", false) <<"\n"; } } return SymbolicExpr::CONTINUE; }
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; }
/** 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; } } }