ROSE 0.11.145.147
TestSemantics.h
1// Perform basic sanity checks on instruction semantics
2#ifndef ROSE_BinaryAnalysis_InstructionSemantics_TestSemantics_H
3#define ROSE_BinaryAnalysis_InstructionSemantics_TestSemantics_H
4#include <featureTests.h>
5#ifdef ROSE_ENABLE_BINARY_ANALYSIS
6
7#include <Rose/BinaryAnalysis/Architecture/Base.h>
8#include <Rose/BinaryAnalysis/BasicTypes.h>
9#include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics.h>
10#include <Rose/CommandLine.h>
11
12namespace Rose {
13namespace BinaryAnalysis {
14namespace InstructionSemantics {
15
28template<class SValuePtr, class RegisterStatePtr, class MemoryStatePtr, class StatePtr, class RiscOperatorsPtr>
30public:
31 typedef typename SValuePtr::Pointee SValue;
32 typedef typename RegisterStatePtr::element_type RegisterState;
33 typedef typename MemoryStatePtr::element_type MemoryState;
34 typedef typename StatePtr::element_type State;
35 typedef typename RiscOperatorsPtr::element_type RiscOperators;
36
38 public:
39 Exception(const std::string &mesg): BaseSemantics::Exception(mesg, NULL) {}
40 };
41
42 void require(bool assertion, const std::string &what_failed) {
43 if (!assertion)
44 throw Exception("failed assertion: "+what_failed);
45 }
46
47 template<typename Pointer>
48 void nonnull(const Pointer &x, const std::string &what_failed) {
49 if (x==NULL)
50 throw Exception("must not be null: "+what_failed);
51 }
52
53 // check boost smart pointers
54 template<class ToPtr, class FromPtr>
55 void check_type(const FromPtr &x, const std::string &what_failed) {
56 typedef typename ToPtr::element_type To;
57 nonnull(x, what_failed);
58 ToPtr y = boost::dynamic_pointer_cast<To>(x);
59 if (y==NULL)
60 throw Exception("wrong pointer type: "+what_failed);
61 }
62
63 // check SValue smart pointers
64 void check_sval_type(const BaseSemantics::SValuePtr &x, const std::string &what_failed) {
65 nonnull(x, what_failed);
66 SValuePtr y = BaseSemantics::dynamic_pointer_cast<SValue>(x);
67 if (y==NULL)
68 throw Exception("wrong pointer type: "+what_failed);
69 }
70
71 // Compile-time checks for SValue
72 class SValueSubclass: public SValue {
73 public:
74 explicit SValueSubclass(size_t nbits): SValue(nbits) {}
75 SValueSubclass(const SValueSubclass &other): SValue(other) {}
76 };
77
78 // Compile-time checks for RegisterState
79 class RegisterStateSubclass: public RegisterState {
80 public:
81 explicit RegisterStateSubclass(const SValuePtr &protoval, const RegisterDictionaryPtr &regdict)
82 : RegisterState(protoval, regdict) {}
83 };
84
85 // Compile-time checks for MemoryState
86 class MemoryStateSubclass: public MemoryState {
87 public:
88 explicit MemoryStateSubclass(const SValuePtr &protoval)
89 : MemoryState(protoval) {}
90 };
91
92 // Compile-time checks for State
93 class StateSubclass: public State {
94 public:
95 StateSubclass(const RegisterStatePtr &registers, const MemoryStatePtr &memory)
96 : State(registers, memory) {}
97 StateSubclass(const StateSubclass &other)
98 : State(other) {}
99 };
100
101 // Compile-time checks for RiscOperators
102 class RiscOperatorsSubclass: public RiscOperators {
103 public:
104 explicit RiscOperatorsSubclass(const SValuePtr &protoval, const SmtSolverPtr &solver = SmtSolverPtr())
105 : RiscOperators(protoval, solver) {}
106 explicit RiscOperatorsSubclass(const StatePtr &state, const SmtSolverPtr &solver = SmtSolverPtr())
107 : RiscOperators(state, solver) {}
108 };
109
110 // Run-time checks
111 void test(const BaseSemantics::RiscOperatorsPtr &ops) {
112 ByteOrder::Endianness savedByteOrder = ops->currentState()->memoryState()->get_byteOrder();
113 ops->currentState()->memoryState()->set_byteOrder(ByteOrder::ORDER_LSB);
114 test(ops->protoval(), ops->currentState(), ops);
115 ops->currentState()->memoryState()->set_byteOrder(ByteOrder::ORDER_MSB);
116 test(ops->protoval(), ops->currentState(), ops);
117 ops->currentState()->memoryState()->set_byteOrder(savedByteOrder);
118 }
119
120 void test(const BaseSemantics::SValuePtr &protoval,
121 const BaseSemantics::StatePtr &state,
123
124 RegisterDictionary::Ptr regdict = Architecture::findByName("amd64").orThrow()->registerDictionary();
125 const RegisterDescriptor reg32 = regdict->findOrThrow("eip");
127
129 // SValue
131
132 SValuePtr v0;
133 require(v0==NULL, "default SValue constructor");
134
135 // Dynamic pointer casts
136 check_sval_type(SValue::promote(protoval), "SValue::promote()");
137
138 // Virtual constructor: undefined_()
139 BaseSemantics::SValuePtr v1 = protoval->undefined_(8);
140 check_sval_type(v1, "SValue::undefined_()");
141 require(v1->nBits()==8, "SValue::undefined_() width");
142
143 // Virtual constructor: unspecified_()
144 BaseSemantics::SValuePtr v1b = protoval->unspecified_(8);
145 check_sval_type(v1b, "SValue::unspecified_()");
146 require(v1b->nBits()==8, "SValue::unspecified() width");
147
148 // Virtual constructor: number_(). Note that we can't check that the number is actually concrete and has a value
149 // because BaseSemantics defines only the API for is_number() and get_number() and not the semantics of those
150 // methods. In fact, the NullSemantics domain doesn't make any distinction between concrete and abstract values--it
151 // treats everything as abstract.
152 BaseSemantics::SValuePtr v2 = protoval->number_(32, 123);
153 check_sval_type(v2, "SValue::number_()");
154 require(v2->nBits()==32, "SValue::number_() width");
155
156 // Virtual constructor: boolean_()
157 BaseSemantics::SValuePtr v3 = protoval->boolean_(true);
158 check_sval_type(v3, "SValue::boolean_()");
159 require(v3->nBits()==1, "SValue::boolean_() width");
160
161 // Virtual constructor: copy()
162 BaseSemantics::SValuePtr v4 = v3->copy();
163 check_sval_type(v4, "SValue::copy()");
164 require(v4!=v3, "SValue::copy() should have returned a new object");
165 require(v4->nBits()==1, "SValue::copy() width");
166 require(v4->isConcrete() == v3->isConcrete(), "copies should be identical");
167 if (v4->isConcrete())
168 require(v4->toUnsigned().get() == v3->toUnsigned().get(), "concrete copies should be identical");
169 std::ostringstream v3str, v4str;
170 v3str <<*v3;
171 v4str <<*v4;
172 require(v3str.str() == v4str.str(), "copies should be identical");
173
174 // may_equal
175 require(v3->mayEqual(v3), "a value may_equal itself");
176 require(v3->mayEqual(v4), "a value may_equal a copy of itself");
177 require(v4->mayEqual(v3), "a value may_equal a copy of itself");
178
179 // mustEqual. Note: must_equal(v3, v4) need not be true when v4 is a copy of v3, although most subclasses do this.
180 require(v3->mustEqual(v3), "a value must_equal itself");
181 require(v3->mustEqual(v4) == v4->mustEqual(v3), "must_equal should be symmetric");
182
183
185 // RegisterState (read/write is tested by RiscOperators)
187
188 // Dynamic pointer cast
189 BaseSemantics::RegisterStatePtr rs1 = state->registerState();
190 check_type<RegisterStatePtr>(RegisterState::promote(rs1), "RegisterState::promote()");
191
192 BaseSemantics::SValuePtr rs1v1 = rs1->protoval();
193 check_sval_type(rs1v1, "RegisterState::protoval()");
194
195 // Virtual constructors
196 BaseSemantics::RegisterStatePtr rs3 = rs1->create(protoval, regdict);
197 check_type<RegisterStatePtr>(rs3, "create()");
198 require(rs3->registerDictionary()==regdict, "RegisterState::create() register dictionary");
199 require(rs3 != rs1, "RegisterState::create() must return a new object");
200 BaseSemantics::SValuePtr rs3v1 = rs3->protoval();
201 check_sval_type(rs3v1, "RegisterState::protoval() after create()");
202
203 BaseSemantics::RegisterStatePtr rs4 = rs1->clone();
204 check_type<RegisterStatePtr>(rs4, "clone()");
205 require(rs4 != rs1, "RegisterState::clone() must return a new object");
206 require(rs4->registerDictionary()==rs1->registerDictionary(),
207 "RegisterState::clone() must use the register dictionary from the source state");
208 BaseSemantics::SValuePtr rs4v1 = rs4->protoval();
209 check_sval_type(rs4v1, "RegisterState::protoval() after clone()");
210
212 // MemoryState (read/write is tested by RiscOperators)
214
215 // Dynamic pointer cast
216 BaseSemantics::MemoryStatePtr ms1 = state->memoryState();
217 check_type<MemoryStatePtr>(MemoryState::promote(ms1), "MemoryState::promote()");
218
219 BaseSemantics::SValuePtr ms1v1 = ms1->get_addr_protoval();
220 check_sval_type(ms1v1, "MemoryState::get_addr_protoval()");
221
222 BaseSemantics::SValuePtr ms1v2 = ms1->get_val_protoval();
223 check_sval_type(ms1v2, "MemoryState::get_val_protoval()");
224
225 // Virtual constructors
226 BaseSemantics::MemoryStatePtr ms2 = ms1->create(protoval, protoval);
227 require(ms2 != ms1, "MemoryState::create() must return a new state");
228 check_type<MemoryStatePtr>(ms2, "MemoryState::create(protoval)");
229 BaseSemantics::SValuePtr ms2v1 = ms2->get_addr_protoval();
230 check_sval_type(ms2v1, "MemoryState::get_addr_protoval() after create");
231 BaseSemantics::SValuePtr ms2v2 = ms2->get_val_protoval();
232 check_sval_type(ms2v2, "MemoryState::get_val_protoval() after create");
233
234 BaseSemantics::MemoryStatePtr ms3 = ms1->clone();
235 require(ms3 != ms1, "MemoryState::clone must return a new state");
236 check_type<MemoryStatePtr>(ms3, "MemoryState::clone()");
237 BaseSemantics::SValuePtr ms3v1 = ms3->get_addr_protoval();
238 check_sval_type(ms3v1, "MemoryState::get_addr_protoval() after clone");
239 BaseSemantics::SValuePtr ms3v2 = ms3->get_val_protoval();
240 check_sval_type(ms3v2, "MemoryState::get_val_protoval() after clone");
241
243 // State (read/write is tested by RiscOperators)
245
246 // Dynamic pointer casts
247 check_type<StatePtr>(State::promote(state), "State::promote()");
248
249 BaseSemantics::SValuePtr state_protoval = state->protoval();
250 check_sval_type(state_protoval, "State::protoval()");
251
252 // Virtual constructors
253 BaseSemantics::StatePtr s1 = state->create(rs1, ms1);
254 require(s1 != state, "State::create() must return a new state");
255 check_type<StatePtr>(s1, "State::create(regs,mem)");
256 require(s1->registerState()==rs1, "State::create() must use supplied register state");
257 require(s1->memoryState()==ms1, "State::create() must use supplied memory state");
258
259 BaseSemantics::StatePtr s2 = state->clone();
260 require(s2 != state, "State::clone() must return a new state");
261 check_type<StatePtr>(s2, "State::clone()");
262 require(s2->registerState() != state->registerState(),
263 "State::clone() must deep-copy the register state");
264 require(s2->memoryState() != state->memoryState(),
265 "State::clone() must deep-copy the memory state");
266
268 // RiscOperators
270
271 // Dynamic pointer casts
272 check_type<RiscOperatorsPtr>(RiscOperators::promote(ops), "RiscOperators::promote()");
273
274 BaseSemantics::SValuePtr ops_protoval = ops->protoval();
275 check_sval_type(ops_protoval, "RiscOperators::protoval()");
276
277 // Virtual constructors
278 BaseSemantics::RiscOperatorsPtr o1 = ops->create(protoval, solver);
279 require(o1 != ops, "RiscOperators::create(protoval,solver) should return a new object");
280 check_type<RiscOperatorsPtr>(o1, "RiscOperators::create(protoval,solver)");
281
282 BaseSemantics::RiscOperatorsPtr o2 = ops->create(state, solver);
283 require(o2 != ops, "RiscOperators::create(state,solver) should return a new object");
284 check_type<RiscOperatorsPtr>(o2, "RiscOperators::create(state,solver)");
285
286 BaseSemantics::StatePtr ops_orig_state = ops->currentState();
287 check_type<StatePtr>(ops_orig_state, "RiscOperators::currentState()");
288
289 // We shouldn't use the supplied state because these tests modify it. So we'll make a copy of the state and use that,
290 // and then restore the original state before we return (but leave our state there fore debugging if there's an
291 // exception). This has the side effect of implicitly checking that State::clone() works because if it didn't the
292 // caller would see the mess we made here. State::clone was tested already.
293 BaseSemantics::StatePtr our_state = ops_orig_state->clone();
294 ops->currentState(our_state);
295 require(ops->currentState() == our_state, "RiscOperators::currentState failed to change state");
296
297 for (size_t i=0; i<4; ++i) {
298 // Value-creating operators
299 BaseSemantics::SValuePtr v32a, v32b, v8, v1;
300 switch (i) {
301 case 0:
302 v32a = ops->undefined_(32);
303 v32b = ops->undefined_(32);
304 v8 = ops->undefined_(8);
305 v1 = ops->undefined_(1);
306 break;
307 case 1:
308 v32a = ops->undefined_(32);
309 v32b = ops->number_(32, 3);
310 v8 = ops->number_(8, 3);
311 v1 = ops->boolean_(false);
312 break;
313 case 2:
314 v32a = ops->number_(32, 4);
315 v32b = ops->undefined_(32);
316 v8 = ops->undefined_(8);
317 v1 = ops->undefined_(1);
318 break;
319 case 3:
320 v32a = ops->number_(32, 4);
321 v32b = ops->number_(32, 3);
322 v8 = ops->number_(8, 3);
323 v1 = ops->boolean_(true);
324 break;
325 }
326 check_sval_type(v32a, "RiscOperators value constructor");
327 require(v32a->nBits()==32, "RiscOperators value constructor width");
328 check_sval_type(v32b, "RiscOperators value constructor");
329 require(v32b->nBits()==32, "RiscOperators value constructor width");
330 check_sval_type(v8, "RiscOperators value constructor");
331 require(v8->nBits()==8, "RiscOperators value constructor width");
332 check_sval_type(v1, "RiscOperators value constructor");
333 require(v1->nBits()==1, "RiscOperators value constructor width");
334
335 // x86-specific operators
336 BaseSemantics::SValuePtr ops_v4 = ops->filterCallTarget(v32a);
337 check_sval_type(ops_v4, "RiscOperators::filterCallTarget");
338 require(ops_v4->nBits()==32, "RiscOperators::filterCallTarget width");
339
340 BaseSemantics::SValuePtr ops_v5 = ops->filterReturnTarget(v32a);
341 check_sval_type(ops_v5, "RiscOperators::filterReturnTarget");
342 require(ops_v5->nBits()==32, "RiscOperators::filterReturnTarget width");
343
344 BaseSemantics::SValuePtr ops_v6 = ops->filterIndirectJumpTarget(v32a);
345 check_sval_type(ops_v6, "RiscOperators::filterIndirectJumpTarget");
346 require(ops_v6->nBits()==32, "RiscOperators::filterIndirectJumpTarget width");
347
348 BaseSemantics::SValuePtr ops_v7 = ops->rdtsc();
349 check_sval_type(ops_v7, "RiscOperators::rdtsc");
350 require(ops_v7->nBits()==64, "RiscOperators::rdtsc width");
351
352 BaseSemantics::SValuePtr ops_v8 = ops->and_(v32a, v32b);
353 check_sval_type(ops_v8, "RiscOperators::and_");
354 require(ops_v8->nBits()==32, "RiscOperators::and_ width");
355
356 BaseSemantics::SValuePtr ops_v9 = ops->or_(v32a, v32b);
357 check_sval_type(ops_v9, "RiscOperators::or_");
358 require(ops_v9->nBits()==32, "RiscOperators::or_ width");
359
360 BaseSemantics::SValuePtr ops_v10 = ops->xor_(v32a, v32b);
361 check_sval_type(ops_v10, "RiscOperators::xor_");
362 require(ops_v10->nBits()==32, "RiscOperators::xor_ width");
363
364 BaseSemantics::SValuePtr ops_v11 = ops->invert(v32a);
365 check_sval_type(ops_v11, "RiscOperators::invert");
366 require(ops_v11->nBits()==32, "RiscOperators::invert width");
367
368 BaseSemantics::SValuePtr ops_v12 = ops->extract(v32a, 5, 8);
369 check_sval_type(ops_v12, "RiscOperators::extract");
370 require(ops_v12->nBits()==3, "RiscOperators::extract width");
371
372 BaseSemantics::SValuePtr ops_v13 = ops->concat(v32a, v32b);
373 check_sval_type(ops_v13, "RiscOperators::concat");
374 require(ops_v13->nBits()==64, "RiscOperators::concat width");
375
376 BaseSemantics::SValuePtr ops_v14 = ops->leastSignificantSetBit(v32a);
377 check_sval_type(ops_v14, "RiscOperators::leastSignificantSetBit");
378 require(ops_v14->nBits()==32, "RiscOperators::leastSignificantSetBit width");
379
380 BaseSemantics::SValuePtr ops_v15 = ops->mostSignificantSetBit(v32a);
381 check_sval_type(ops_v15, "RiscOperators::mostSignificantSetBit");
382 require(ops_v15->nBits()==32, "RiscOperators::mostSignificantSetBit width");
383
384 BaseSemantics::SValuePtr ops_v16 = ops->rotateLeft(v32a, v8);
385 check_sval_type(ops_v16, "RiscOperators::rotateLeft");
386 require(ops_v16->nBits()==32, "RiscOperators::rotateLeft width");
387
388 BaseSemantics::SValuePtr ops_v17 = ops->rotateRight(v32a, v8);
389 check_sval_type(ops_v17, "RiscOperators::rotateRight");
390 require(ops_v17->nBits()==32, "RiscOperators::rotateRight width");
391
392 BaseSemantics::SValuePtr ops_v18 = ops->shiftLeft(v32a, v8);
393 check_sval_type(ops_v18, "RiscOperators::shiftLeft");
394 require(ops_v18->nBits()==32, "RiscOperators::shiftLeft width");
395
396 BaseSemantics::SValuePtr ops_v19 = ops->shiftRight(v32a, v8);
397 check_sval_type(ops_v19, "RiscOperators::shiftRight");
398 require(ops_v19->nBits()==32, "RiscOperators::shiftRight width");
399
400 BaseSemantics::SValuePtr ops_v20 = ops->shiftRightArithmetic(v32a, v8);
401 check_sval_type(ops_v20, "RiscOperators::shiftRightArithmetic");
402 require(ops_v20->nBits()==32, "RiscOperators::shiftRightArithmetic width");
403
404 BaseSemantics::SValuePtr ops_v21 = ops->equalToZero(v32a);
405 check_sval_type(ops_v21, "RiscOperators::equalToZero");
406 require(ops_v21->nBits()==1, "RiscOperators::equalToZero width");
407
408 BaseSemantics::SValuePtr ops_v22 = ops->ite(v1, v32a, v32b);
409 check_sval_type(ops_v22, "RiscOperators::ite");
410 require(ops_v22->nBits()==32, "RiscOperators::ite width");
411
413 BaseSemantics::SValuePtr ops_v22b = ops->iteWithStatus(v1, v32a, v32b, status1);
414 check_sval_type(ops_v22b, "RiscOperators::iteWithStatus");
415 require(ops_v22b->nBits() == 32, "RiscOperators::iteWithStatus width");
416
417 BaseSemantics::SValuePtr ops_v23 = ops->unsignedExtend(v8, 32);
418 check_sval_type(ops_v23, "RiscOperators::unsignedExtend");
419 require(ops_v23->nBits()==32, "RiscOperators::unsignedExtend width");
420
421 BaseSemantics::SValuePtr ops_v24 = ops->unsignedExtend(v32a, 8);
422 check_sval_type(ops_v24, "RiscOperators::unsignedExtend truncate");
423 require(ops_v24->nBits()==8, "RiscOperators::unsignedExtend truncate width");
424
425 BaseSemantics::SValuePtr ops_v25 = ops->signExtend(v8, 32);
426 check_sval_type(ops_v25, "RiscOperators::signExtend");
427 require(ops_v25->nBits()==32, "RiscOperators::signExtend width");
428
429 BaseSemantics::SValuePtr ops_v26 = ops->add(v32a, v32b);
430 check_sval_type(ops_v26, "RiscOperators::add");
431 require(ops_v26->nBits()==32, "RiscOperators::add width");
432
433 BaseSemantics::SValuePtr carry_out;
434 BaseSemantics::SValuePtr ops_v27 = ops->addWithCarries(v32a, v32b, v1, carry_out);
435 check_sval_type(ops_v27, "RiscOperators::addWithCarries");
436 require(ops_v27->nBits()==32, "RiscOperators::addWithCarries width");
437 check_sval_type(carry_out, "RiscOperators::addWithCarries carry_out");
438 require(carry_out->nBits()==32, "RiscOperators::addWithCarries carry_out width");
439
440 BaseSemantics::SValuePtr ops_v28 = ops->negate(v32a);
441 check_sval_type(ops_v28, "RiscOperators::negate");
442 require(ops_v28->nBits()==32, "RiscOperators::negate width");
443
444 try {
445 BaseSemantics::SValuePtr ops_v29 = ops->signedDivide(v32a, v8);
446 check_sval_type(ops_v29, "RiscOperators::signedDivide");
447 require(ops_v29->nBits()==32, "RiscOperators::signedDivide width");
448 } catch (const BaseSemantics::Exception&) {
449 // possible division by zero
450 }
451
452 try {
453 BaseSemantics::SValuePtr ops_v30 = ops->signedModulo(v32a, v8);
454 check_sval_type(ops_v30, "RiscOperators::signedModulo");
455 require(ops_v30->nBits()==8, "RiscOperators::signedModulo width");
456 } catch (const BaseSemantics::Exception&) {
457 // possible division by zero
458 }
459
460 BaseSemantics::SValuePtr ops_v31 = ops->signedMultiply(v32a, v8);
461 check_sval_type(ops_v31, "RiscOperators::signedMultiply");
462 require(ops_v31->nBits()==40, "RiscOperators::signedMultiply width");
463
464 try {
465 BaseSemantics::SValuePtr ops_v32 = ops->unsignedDivide(v32a, v8);
466 check_sval_type(ops_v32, "RiscOperators::unsignedDivide");
467 require(ops_v32->nBits()==32, "RiscOperators::unsignedDivide width");
468 } catch (const BaseSemantics::Exception&) {
469 // possible division by zero
470 }
471
472 try {
473 BaseSemantics::SValuePtr ops_v33 = ops->unsignedModulo(v32a, v8);
474 check_sval_type(ops_v33, "RiscOperators::unsignedModulo");
475 require(ops_v33->nBits()==8, "RiscOperators::unsignedModulo width");
476 } catch (const BaseSemantics::Exception&) {
477 // possible division by zero
478 }
479
480 BaseSemantics::SValuePtr ops_v34 = ops->unsignedMultiply(v32a, v8);
481 check_sval_type(ops_v34, "RiscOperators::unsignedMultiply");
482 require(ops_v34->nBits()==40, "RiscOperators::unsignedMultiply width");
483
484 BaseSemantics::SValuePtr ops_v35 = ops->readRegister(reg32);
485 check_sval_type(ops_v35, "RiscOperators::readRegister");
486 require(ops_v35->nBits()==32, "RiscOperators::readRegister width");
487
488 // We can't really check many semantics for readMemory because each MemoryState might behave differently. For
489 // example, we can't check that reading the same address twice in a row returns the same value both times because
490 // the NullSemantics doesn't have this property.
491
492 BaseSemantics::SValuePtr dflt8 = ops->number_(8, 0);
493 BaseSemantics::SValuePtr ops_v36 = ops->readMemory(RegisterDescriptor(), v32a, dflt8, v1);
494 check_sval_type(ops_v36, "RiscOperators::readMemory byte");
495 require(ops_v36->nBits()==8, "RiscOperators::readMemory byte width");
496
497 BaseSemantics::SValuePtr dflt32 = ops->number_(32, 0);
498 BaseSemantics::SValuePtr ops_v37 = ops->readMemory(RegisterDescriptor(), v32a, dflt32, v1);
499 check_sval_type(ops_v37, "RiscOperators::readMemory word");
500 require(ops_v37->nBits()==32, "RiscOperators::readMemory word width");
501
502 // Nothing to check for write memory other than that we can actually call it. The problem is that writeMemory only
503 // modifies a state and doesn't return anything we can test. The specifics of how it modifies a memory state is
504 // entirely up to the implementation, so we can't even test that writing a value to an address and then reading
505 // from that address returns the value that was written (e.g., NullSemantics doesn't have this property).
506
507 ops->writeMemory(RegisterDescriptor(), v32a, dflt32, v1);
508
509 }
510
511 // Restore the original state
512 ops->currentState(ops_orig_state);
513 }
514};
515
516} // namespace
517} // namespace
518} // namespace
519
520#endif
521#endif
Provides functions for testing binary instruction semantics.
Describes (part of) a physical CPU register.
static Ptr instance(const std::string &name)
Allocate a new solver by name.
Base class for all ROSE exceptions.
Sawyer::Result< BasePtr, NotFound > findByName(const std::string &)
Look up a new architecture by name.
@ ORDER_MSB
Most significant byte first, i.e., big-endian.
Definition ByteOrder.h:23
@ ORDER_LSB
Least significant byte first, i.e., little-endian.
Definition ByteOrder.h:22
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
boost::shared_ptr< MemoryState > MemoryStatePtr
Shared-ownership pointer to a memory state.
boost::shared_ptr< RegisterState > RegisterStatePtr
Shared-ownership pointer to a register state.
std::shared_ptr< SmtSolver > SmtSolverPtr
Reference counting pointer.
ROSE_DLL_API GenericSwitchArgs genericSwitchArgs
Global location for parsed generic command-line switches.
The ROSE library.
const char * ops(int64_t)
Convert ops enum constant to a string.