/** 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; }
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; }
/** 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); } } }