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