ROSE  0.11.98.0
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/BasicTypes.h>
8 #include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics.h>
9 #include <Rose/BinaryAnalysis/RegisterDictionary.h>
10 #include <Rose/CommandLine.h>
11 
12 namespace Rose {
13 namespace BinaryAnalysis { // documented elsewhere
14 namespace InstructionSemantics { // documented elsewhere
15 
28 template<class SValuePtr, class RegisterStatePtr, class MemoryStatePtr, class StatePtr, class RiscOperatorsPtr>
30 public:
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,
122  const BaseSemantics::RiscOperatorsPtr &ops) {
123 
125  const RegisterDescriptor reg32 = regdict->findOrThrow("eip");
126  SmtSolverPtr solver = SmtSolver::instance(Rose::CommandLine::genericSwitchArgs.smtSolver);
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
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
Provides functions for testing binary instruction semantics.
Definition: TestSemantics.h:29
boost::shared_ptr< RegisterState > RegisterStatePtr
Shared-ownership pointer to a register state.
Main namespace for the ROSE library.
boost::shared_ptr< State > StatePtr
Shared-ownership pointer to a semantic state.
boost::shared_ptr< MemoryState > MemoryStatePtr
Shared-ownership pointer to a memory state.
static Ptr instance(const std::string &name)
Allocate a new solver by name.
Describes (part of) a physical CPU register.
Binary analysis.
static Ptr instancePentium4()
Intel Pentium 4 registers.
Base class for all ROSE exceptions.
Definition: Rose/Exception.h:9
ROSE_DLL_API GenericSwitchArgs genericSwitchArgs
Global location for parsed generic command-line switches.