Esempio n. 1
0
/** 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()) + "))");
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
/** Generate a Yices "assert" statement for an expression. */
void
YicesSolver::out_assert(std::ostream &o, const SymbolicExpr::Ptr &tn)
{
    o <<"(assert ";
    if (tn->isNumber() && 1==tn->nBits()) {
        if (tn->toInt()) {
            o <<"true";
        } else {
            o <<"false";
        }
    } else {
        out_expr(o, tn);
    }
    o <<")\n";
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
 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;
 }
Esempio n. 7
0
/** 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();
}
Esempio n. 8
0
/** Output for arithmetic right shift.  Yices doesn't have a sign-extending right shift, therefore we implement it in terms of
 *  other operations.  (OP_ASR ShiftAmount Vector) becomes
 *
 *  (ite (= (mk-bv 1 1) (bv-extract [VectorSize-1] [VectorSize-1] Vector)) ;; vector's sign bit
 *       (bv-shift-right1 Vector [ShiftAmount])
 *       (bv-shift-right0 Vector [ShiftAmount]))
 *
 * where [VectorSize], [VectorSize-1], and [ShiftAmount] are numeric constants.
 */
void
YicesSolver::out_asr(std::ostream &o, const SymbolicExpr::InteriorPtr &in)
{
    ASSERT_require(in && 2==in->nChildren());
    SymbolicExpr::Ptr vector = in->child(1);
    uint64_t vector_size = vector->nBits();
    ASSERT_require(in->child(0)->isNumber());
    uint64_t shift_amount = in->child(0)->toInt();

    o <<"(ite (= (mk-bv 1 1) (bv-extract " <<(vector_size-1) <<" " <<(vector_size-1) <<" ";
    out_expr(o, vector);
    o <<")) (bv-shift-right1 ";
    out_expr(o, vector);
    o <<" " <<shift_amount <<") (bv-shift-right0 ";
    out_expr(o, vector);
    o <<" " <<shift_amount <<"))";
}
Esempio n. 9
0
/** 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;
}
Esempio n. 10
0
/** 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);
        }
    }
}
Esempio n. 11
0
 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;
 }
Esempio n. 12
0
 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;
 }
Esempio n. 13
0
/** 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;
        }
    }
}
Esempio n. 14
0
int
main(int argc, char *argv[]) {
    bool testSerialization = false;
    parseCommandLine(argc, argv, testSerialization /*in,out*/);
    unsigned lineNumber = 0;
    while (1) {

        // Prompt for and read a line containing one expression
        ++lineNumber;
#ifdef ROSE_HAVE_LIBREADLINE
        char *line = readline("> ");
        if (!line)
            break;
        add_history(line);
#else
        char *line = NULL;
        size_t linesz = 0;
        printf("> ");
        ssize_t nread = rose_getline(&line, &linesz, stdin);
        if (nread <= 0)
            break;
        while (nread > 0 && isspace(line[nread-1]))
            line[--nread] = '\0';
#endif

        // Parse the expression
        try {
            SymbolicExpr::Ptr expr = symbolicParser().parse(line);
            std::cout <<"Parsed value = " <<*expr <<"\n\n";
#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
            if (testSerialization) {
                std::cout <<"Serializing\n";
                std::ostringstream oss;
                boost::archive::text_oarchive out(oss);
                out.template register_type<SymbolicExpr::Interior>();
                out.template register_type<SymbolicExpr::Leaf>();
                out <<expr;

                std::cout <<"Deserializing\n";
                std::istringstream iss(oss.str());
                boost::archive::text_iarchive in(iss);
                SymbolicExpr::Ptr expr2;
                in.template register_type<SymbolicExpr::Interior>();
                in.template register_type<SymbolicExpr::Leaf>();
                in >>expr2;

                std::cout <<"Restored value = " <<*expr2 <<"\n\n";
                if (!expr->isEquivalentTo(expr2))
                    std::cerr <<"error: serialization failed structural equivalence test\n";
            }
#endif
        } catch (const SymbolicExprParser::SyntaxError &e) {
            std::cerr <<e <<"\n";
            if (e.lineNumber != 0) {
                std::cerr <<"    input: " <<line <<"\n"
                          <<"    here---" <<std::string(e.columnNumber, '-') <<"^\n\n";
            }
        } catch (const rose::FailedAssertion &e) {
            std::cerr <<"\n"; // message has already been printed.
        }

        free(line);
    }
}