//! [basicReadTest] static void basicReadTest(const P2::Partitioner &partitioner) { std::cout <<"\n" <<std::string(40, '=') <<"\nbasicReadTest\n" <<std::string(40, '=') <<"\n"; SymbolicSemantics::Formatter fmt; fmt.set_line_prefix(" "); // Create the RiscOperators and the initial state. const RegisterDictionary *regdict = partitioner.instructionProvider().registerDictionary(); const RegisterDescriptor REG = partitioner.instructionProvider().stackPointerRegister(); const std::string REG_NAME = RegisterNames(regdict)(REG); BaseSemantics::RiscOperatorsPtr ops = SymbolicSemantics::RiscOperators::instance(regdict); ops->currentState()->memoryState()->set_byteOrder(partitioner.instructionProvider().defaultByteOrder()); BaseSemantics::StatePtr initialState = ops->currentState()->clone(); ops->initialState(initialState); // lazily evaluated initial state std::cout <<"Initial state before reading:\n" <<(*initialState+fmt); // Read some memory and a register, which should cause them to spring into existence in both the current state and the // initial state. BaseSemantics::SValuePtr addr1 = ops->number_(32, 0); BaseSemantics::SValuePtr dflt1m = ops->number_(32, 0x11223344); BaseSemantics::SValuePtr read1m = ops->readMemory(RegisterDescriptor(), addr1, dflt1m, ops->boolean_(true)); BaseSemantics::SValuePtr dflt1r = ops->undefined_(REG.get_nbits()); BaseSemantics::SValuePtr read1r = ops->readRegister(REG, dflt1r); std::cout <<"Initial state after reading " <<*read1m <<" from address " <<*addr1 <<"\n" <<"and " <<*read1r <<" from " <<REG_NAME <<"\n" <<(*initialState+fmt); ASSERT_always_require(read1m->must_equal(dflt1m)); ASSERT_always_require(read1r->must_equal(dflt1r)); // Create a new current state and read again. We should get the same value even though the current state is empty. BaseSemantics::StatePtr curState = ops->currentState()->clone(); curState->clear(); ops->currentState(curState); BaseSemantics::SValuePtr dflt2m = ops->number_(32, 0x55667788); BaseSemantics::SValuePtr read2m = ops->readMemory(RegisterDescriptor(), addr1, dflt2m, ops->boolean_(true)); BaseSemantics::SValuePtr dflt2r = ops->undefined_(REG.get_nbits()); BaseSemantics::SValuePtr read2r = ops->readRegister(REG, dflt2r); std::cout <<"Initial state after reading " <<*read2m <<" from address " <<*addr1 <<"\n" <<"and " <<*read2r <<" from " <<REG_NAME <<"\n" <<(*initialState+fmt); ASSERT_always_require(read1m->must_equal(read2m)); ASSERT_always_require(read1r->must_equal(read2r)); // Disable the initial state. If we re-read the same address we'll still get the same result because it's now present in // the current state also. ops->initialState(BaseSemantics::StatePtr()); BaseSemantics::SValuePtr dflt3m = ops->number_(32, 0x99aabbcc); BaseSemantics::SValuePtr read3m = ops->readMemory(RegisterDescriptor(), addr1, dflt3m, ops->boolean_(true)); BaseSemantics::SValuePtr dflt3r = ops->undefined_(REG.get_nbits()); BaseSemantics::SValuePtr read3r = ops->readRegister(REG, dflt3r); ASSERT_always_require(read1m->must_equal(read3m)); ASSERT_always_require(read1r->must_equal(read3r)); }
int main(int argc, char *argv[]) { ROSE_INITIALIZE; Diagnostics::initAndRegister(&::mlog, "tool"); parseCommandLine(argc, argv); // Create the machine state const RegisterDictionary *registers = RegisterDictionary::dictionary_amd64(); const RegisterDescriptor EAX = *registers->lookup("eax"); SmtSolverPtr solver; BaseSemantics::RiscOperatorsPtr ops = SymbolicSemantics::RiscOperators::instance(registers, solver); ops->currentState()->memoryState()->set_byteOrder(ByteOrder::ORDER_LSB); // Initialize the machine state with some writes and get the string representation. BaseSemantics::SValuePtr eax = ops->number_(32, 1234); ops->writeRegister(EAX, eax); BaseSemantics::SValuePtr addr0 = ops->number_(32, 0x1000); BaseSemantics::SValuePtr mem0 = ops->number_(8, 123); ops->writeMemory(RegisterDescriptor(), addr0, mem0, ops->boolean_(true)); std::ostringstream s0; s0 <<*ops; // Peek at parts of the state that exist BaseSemantics::SValuePtr v1 = ops->peekRegister(EAX, ops->undefined_(32)); ASSERT_always_not_null(v1); ASSERT_always_require(v1->must_equal(eax, solver)); BaseSemantics::SValuePtr mem1 = ops->peekMemory(RegisterDescriptor(), addr0, ops->undefined_(8)); ASSERT_always_not_null(mem1); ASSERT_always_require(mem1->must_equal(mem0, solver)); std::ostringstream s1; s1 <<*ops; ASSERT_always_require2(s0.str() == s1.str(), s1.str()); // Peek at parts of the state that don't exist const RegisterDescriptor EBX = *registers->lookup("ebx"); BaseSemantics::SValuePtr ebx = ops->undefined_(32); BaseSemantics::SValuePtr v2 = ops->peekRegister(EBX, ebx); ASSERT_always_not_null(v2); ASSERT_always_require(v2->must_equal(ebx, solver)); BaseSemantics::SValuePtr addr2 = ops->number_(32, 0x2000); BaseSemantics::SValuePtr mem2init = ops->undefined_(8); BaseSemantics::SValuePtr mem2 = ops->peekMemory(RegisterDescriptor(), addr2, mem2init); ASSERT_always_not_null(mem2); ASSERT_always_require(mem2->must_equal(mem2init, solver)); std::ostringstream s2; s2 <<*ops; ASSERT_always_require2(s0.str() == s2.str(), s2.str()); // Peek at parts of the state that partly exist. const RegisterDescriptor RAX = *registers->lookup("rax"); BaseSemantics::SValuePtr zero64 = ops->number_(64, 0); BaseSemantics::SValuePtr v3 = ops->peekRegister(RAX, zero64); ASSERT_always_not_null(v3); ASSERT_always_require(v3->must_equal(ops->number_(64, 1234), solver)); BaseSemantics::SValuePtr zero32 = ops->number_(32, 0); BaseSemantics::SValuePtr mem3ans = ops->number_(32, 123); BaseSemantics::SValuePtr mem3 = ops->peekMemory(RegisterDescriptor(), addr0, zero32); ASSERT_always_not_null(mem3); ASSERT_always_require(mem3->must_equal(mem3ans, solver)); std::ostringstream s3; s3 <<*ops; ASSERT_always_require2(s0.str() == s3.str(), s3.str()); std::cout <<s3.str(); }