1use std::ops::Range;
19use std::fmt;
20use smallvec::SmallVec;
21use quickcheck::{Arbitrary, Gen};
22use ron_uuid::UUID;
23
24use {
25 StrRef, Str,
26 Variable, Value, Constant, Segment,
27 Result, Constraint
28};
29
30#[derive(Clone,PartialEq,Eq)]
33pub struct Area {
34 pub start: u64,
36 pub end: u64,
38 pub offset_start: usize,
40 pub offset_end: usize,
42}
43
44impl From<Range<u64>> for Area {
45 fn from(r: Range<u64>) -> Self {
46 Area{
47 start: r.start,
48 end: r.end,
49 offset_start: 0,
50 offset_end: if r.end == r.start { 1 } else { 0 },
51 }
52 }
53}
54
55impl fmt::Debug for Area {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 if self.offset_start != 0 {
58 write!(f, "{}.{}..", self.start, self.offset_start)?;
59 } else {
60 write!(f, "{}..", self.start)?;
61 }
62 if self.offset_end != 0 {
63 write!(f, "{}.{}", self.end, self.offset_end)
64 } else {
65 write!(f, "{}", self.end)
66 }
67 }
68}
69
70#[derive(Debug,Clone,Copy,PartialEq,Eq)]
72pub enum Endianess {
73 Little,
75 Big,
77}
78
79impl Arbitrary for Endianess {
80 fn arbitrary<G: Gen>(g: &mut G) -> Self {
81 match g.gen_range(0, 1) {
82 0 => Endianess::Little,
83 1 => Endianess::Big,
84 _ => unreachable!(),
85 }
86 }
87}
88
89#[derive(Clone,PartialEq,Eq,Debug)]
91pub enum Operation {
92 Add(Value, Value),
94 Subtract(Value, Value),
96 Multiply(Value, Value),
98 DivideUnsigned(Value, Value),
100 DivideSigned(Value, Value),
102 ShiftLeft(Value, Value),
104 ShiftRightUnsigned(Value, Value),
106 ShiftRightSigned(Value, Value),
108 Modulo(Value, Value),
110 And(Value, Value),
112 InclusiveOr(Value, Value),
114 ExclusiveOr(Value, Value),
116
117 Equal(Value, Value),
119 LessOrEqualUnsigned(Value, Value),
122 LessOrEqualSigned(Value, Value),
125 LessUnsigned(Value, Value),
128 LessSigned(Value, Value),
131
132 ZeroExtend(usize, Value),
134 SignExtend(usize, Value),
136 Move(Value),
138 Initialize(StrRef,usize),
140 Select(usize, usize, Value),
142 Assume(Constraint,Value),
144 Load(Segment,Endianess,usize,Value),
146
147 Phi(Value,Value,Value),
149}
150
151impl Operation {
152 pub fn reads<'x>(&'x self) -> SmallVec<[&'x Value; 3]> {
154 use Operation::*;
155
156 let mut ret = SmallVec::new();
157
158 match self {
159 &Add(ref a, ref b) => { ret.push(a); ret.push(b); }
160 &Subtract(ref a, ref b) => { ret.push(a); ret.push(b); }
161 &Multiply(ref a, ref b) => { ret.push(a); ret.push(b); }
162 &DivideUnsigned(ref a, ref b) => { ret.push(a); ret.push(b); }
163 &DivideSigned(ref a, ref b) => { ret.push(a); ret.push(b); }
164 &ShiftLeft(ref a, ref b) => { ret.push(a); ret.push(b); }
165 &ShiftRightUnsigned(ref a, ref b) => { ret.push(a); ret.push(b); }
166 &ShiftRightSigned(ref a, ref b) => { ret.push(a); ret.push(b); }
167 &Modulo(ref a, ref b) => { ret.push(a); ret.push(b); }
168 &And(ref a, ref b) => { ret.push(a); ret.push(b); }
169 &InclusiveOr(ref a, ref b) => { ret.push(a); ret.push(b); }
170 &ExclusiveOr(ref a, ref b) => { ret.push(a); ret.push(b); }
171
172 &Equal(ref a, ref b) => { ret.push(a); ret.push(b); }
173 &LessOrEqualUnsigned(ref a, ref b) => { ret.push(a); ret.push(b); }
174 &LessOrEqualSigned(ref a, ref b) => { ret.push(a); ret.push(b); }
175 &LessUnsigned(ref a, ref b) => { ret.push(a); ret.push(b); }
176 &LessSigned(ref a, ref b) => { ret.push(a); ret.push(b); }
177
178 &ZeroExtend(_, ref a) => { ret.push(a); }
179 &SignExtend(_, ref a) => { ret.push(a); }
180 &Move(ref a) => { ret.push(a); }
181 &Initialize(_,_) => {}
182 &Select(_, _, ref a) => { ret.push(a); }
183 &Assume(_, ref a) => { ret.push(a); }
184
185 &Load(_, _, _, ref a) => { ret.push(a); }
186
187 &Phi(ref a, ref b, ref c) => {
188 ret.push(a); ret.push(b); ret.push(c);
189 }
190 }
191
192 ret
193 }
194
195 pub fn reads_mut<'x>(&'x mut self) -> SmallVec<[&'x mut Value; 3]> {
197 use Operation::*;
198
199 let mut ret = SmallVec::new();
200
201 match self {
202 &mut Add(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
203 &mut Subtract(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
204 &mut Multiply(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
205 &mut DivideUnsigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
206 &mut DivideSigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
207 &mut ShiftLeft(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
208 &mut ShiftRightUnsigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
209 &mut ShiftRightSigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
210 &mut Modulo(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
211 &mut And(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
212 &mut InclusiveOr(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
213 &mut ExclusiveOr(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
214
215 &mut Equal(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
216 &mut LessOrEqualUnsigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
217 &mut LessOrEqualSigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
218 &mut LessUnsigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
219 &mut LessSigned(ref mut a, ref mut b) => { ret.push(a); ret.push(b); }
220
221 &mut ZeroExtend(_, ref mut a) => { ret.push(a); }
222 &mut SignExtend(_, ref mut a) => { ret.push(a); }
223 &mut Move(ref mut a) => { ret.push(a); }
224 &mut Initialize(_,_) => {}
225 &mut Select(_, _, ref mut a) => { ret.push(a); }
226 &mut Assume(_, ref mut a) => { ret.push(a); }
227
228 &mut Load(_, _, _, ref mut a) => { ret.push(a); }
229
230 &mut Phi(ref mut a, ref mut b, ref mut c) => {
231 ret.push(a); ret.push(b); ret.push(c);
232 }
233 }
234
235 ret
236 }
237
238 pub fn execute(&self) -> Result<Value> {
240 use std::num::Wrapping;
241 use Operation::*;
242 use std::u64;
243
244 match self.clone() {
245 Add(Value::Constant(a), Value::Constant(b)) => {
246 if a.bits != b.bits {
247 return Err(format!("tried to add value of {} and {} bits",a.bits,b.bits).into());
248 }
249
250 let mask = a.mask();
251 let bits = a.bits;
252 let a: Wrapping<_> = a.into();
253 let b: Wrapping<_> = b.into();
254 Value::val(((a + b) & mask).0, bits)
255 }
256 Add(Value::Constant(Constant { value: 0, .. }), b) => Ok(b),
257 Add(a, Value::Constant(Constant { value: 0, .. })) => Ok(a),
258 Add(_, _) => Ok(Value::Undefined),
259
260 Subtract(Value::Constant(a), Value::Constant(b)) => {
261 if a.bits != b.bits {
262 return Err(format!("tried to subtract value of {} and {} bits",a.bits,b.bits).into());
263 }
264
265 let mask = a.mask();
266 let bits = a.bits;
267 let a: Wrapping<_> = a.into();
268 let b: Wrapping<_> = b.into();
269 Value::val(((a - b) & mask).0, bits)
270 }
271 Subtract(a, Value::Constant(Constant { value: 0, .. })) => Ok(a),
272 Subtract(_, _) => Ok(Value::Undefined),
273
274 Multiply(Value::Constant(a), Value::Constant(b)) => {
275 if a.bits != b.bits {
276 return Err(format!("tried to multiply value of {} and {} bits",a.bits,b.bits).into());
277 }
278
279 let mask = a.mask();
280 let bits = a.bits;
281 let a: Wrapping<_> = a.into();
282 let b: Wrapping<_> = b.into();
283 Value::val(((a * b) & mask).0, bits)
284 }
285 Multiply(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
286 Multiply(_, Value::Constant(Constant { value: 0, bits: s })) => Ok(Value::Constant(Constant { value: 0, bits: s })),
287 Multiply(Value::Constant(Constant { value: 1, .. }), b) => Ok(b),
288 Multiply(a, Value::Constant(Constant { value: 1, .. })) => Ok(a),
289 Multiply(_, _) => Ok(Value::Undefined),
290
291 DivideUnsigned(Value::Constant(a), Value::Constant(b)) => {
292 if a.bits != b.bits {
293 return Err(format!("tried to divide value of {} and {} bits",a.bits,b.bits).into());
294 }
295
296 let mask = a.mask();
297 let bits = a.bits;
298 let a: Wrapping<_> = a.into();
299 let b: Wrapping<_> = b.into();
300
301 if b == Wrapping(0) {
302 Ok(Value::Undefined)
303 } else {
304 Value::val(((a / b) & mask).0, bits)
305 }
306 }
307 DivideUnsigned(a, Value::Constant(Constant { value: 1, .. })) => Ok(a),
308 DivideUnsigned(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
309 DivideUnsigned(_, _) => Ok(Value::Undefined),
310
311 DivideSigned(Value::Constant(a), Value::Constant(b)) => {
312 if a.bits != b.bits {
313 return Err(format!("tried to divide value of {} and {} bits",a.bits,b.bits).into());
314 }
315
316 let bits = a.bits;
317 let mut a = Wrapping(a.value as i64);
318 let mut b = Wrapping(b.value as i64);
319
320 if bits < 64 {
321 let sign_bit = Wrapping(1 << (bits - 1));
322 let m = Wrapping(1 << bits);
323
324 if sign_bit & a != Wrapping(0) {
325 a = a - m;
326 }
327 if sign_bit & b != Wrapping(0) {
328 b = b - m;
329 }
330 a = a % m;
331 b = b % m;
332 }
333
334 if b == Wrapping(0) {
335 Ok(Value::Undefined)
336 } else {
337 if bits < 64 {
338 let m = 1 << bits;
339 Value::val((a / b).0 as u64 % m, bits)
340 } else {
341 Value::val((a / b).0 as u64, bits)
342 }
343 }
344 }
345 DivideSigned(a, Value::Constant(Constant { value: 1, .. })) => Ok(a),
346 DivideSigned(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
347 DivideSigned(_, _) => Ok(Value::Undefined),
348
349 Modulo(_, Value::Constant(Constant { value: 0, .. })) => Ok(Value::Undefined),
350 Modulo(Value::Constant(a), Value::Constant(b)) => {
351 if a.bits != b.bits {
352 return Err(format!("tried to mod value of {} and {} bits",a.bits,b.bits).into());
353 }
354
355 let mask = a.mask();
356 let bits = a.bits;
357 let a: Wrapping<_> = a.into();
358 let b: Wrapping<_> = b.into();
359
360 if b == Wrapping(0) {
361 Ok(Value::Undefined)
362 } else {
363 Value::val(((a % b) & mask).0, bits)
364 }
365 }
366 Modulo(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
367 Modulo(_, Value::Constant(Constant { value: 1, bits: s })) => Ok(Value::Constant(Constant { value: 0, bits: s })),
368 Modulo(_, _) => Ok(Value::Undefined),
369
370 ShiftLeft(Value::Constant(a), Value::Constant(b)) => {
371 let mask = a.mask();
372 let bits = a.bits;
373 let a: Wrapping<_> = a.into();
374 let b: Wrapping<_> = b.into();
375
376 Value::val(((a << (b.0 as usize)) & mask).0, bits)
377 }
378 ShiftLeft(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
379 ShiftLeft(a, Value::Constant(Constant { value: 0, .. })) => Ok(a),
380 ShiftLeft(_, _) => Ok(Value::Undefined),
381
382 ShiftRightUnsigned(Value::Constant(a), Value::Constant(b)) => {
383 use std::cmp;
384
385 if a.bits != b.bits {
386 return Err(format!("tried to mod value of {} and {} bits",a.bits,b.bits).into());
387 }
388
389 let mask = a.mask();
390 let bits = a.bits;
391 let a: Wrapping<_> = a.into();
392 let b: Wrapping<_> = b.into();
393
394 if b.0 >= bits as u64 {
395 Value::val(0, bits)
396 } else {
397 Value::val(((a >> cmp::min(cmp::min(64, bits), b.0 as usize)) & mask).0,bits)
398 }
399 }
400 ShiftRightUnsigned(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
401 ShiftRightUnsigned(a, Value::Constant(Constant { value: 0, .. })) => Ok(a),
402 ShiftRightUnsigned(_, _) => Ok(Value::Undefined),
403
404 ShiftRightSigned(Value::Constant(a), Value::Constant(b)) => {
405 if a.bits != b.bits {
406 return Err(format!("tried to mod value of {} and {} bits",a.bits,b.bits).into());
407 }
408
409 let mask = a.mask();
410 let bits = a.bits;
411 let mut a = Wrapping(a.value as i64);
412 let b = Wrapping(b.value as i64);
413
414 if bits < 64 {
415 let sign_bit = Wrapping(1 << (bits - 1));
416 if sign_bit & a != Wrapping(0) {
417 a = a | Wrapping(-1i64 << bits);
418 }
419 }
420
421 if b.0 as u64 >= bits as u64 {
422 let ret = if a < Wrapping(0) {
423 if bits < 64 {
424 Value::Constant(Constant { value: (1 << bits) - 1, bits: bits })
425 } else {
426 Value::Constant(Constant { value: u64::MAX, bits: bits })
427 }
428 } else {
429 Value::Constant(Constant { value: 0, bits: bits })
430 };
431 Ok(ret)
432 } else {
433 if bits < 64 {
434 Value::val((a >> (b.0 as usize)).0 as u64 & mask.0, bits)
435 } else {
436 Value::val((a >> (b.0 as usize)).0 as u64, bits)
437 }
438 }
439 }
440 ShiftRightSigned(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
441 ShiftRightSigned(a, Value::Constant(Constant { value: 0, .. })) => Ok(a),
442 ShiftRightSigned(_, _) => Ok(Value::Undefined),
443
444 And(Value::Constant(a), Value::Constant(b)) => {
445 if a.bits != b.bits {
446 return Err(format!("tried to and value of {} and {} bits",a.bits,b.bits).into());
447 }
448
449 let bits = a.bits;
450 let a: Wrapping<_> = a.into();
451 let b: Wrapping<_> = b.into();
452
453 Value::val((a & b).0 as u64, bits)
454 }
455 And(_, Value::Constant(Constant { value: 0, bits: s })) => Ok(Value::Constant(Constant { value: 0, bits: s })),
456 And(Value::Constant(Constant { value: 0, bits: s }), _) => Ok(Value::Constant(Constant { value: 0, bits: s })),
457 And(_, _) => Ok(Value::Undefined),
458
459 InclusiveOr(Value::Constant(a), Value::Constant(b)) => {
460 if a.bits != b.bits {
461 return Err(format!("tried to or value of {} and {} bits",a.bits,b.bits).into());
462 }
463
464 let bits = a.bits;
465 let a: Wrapping<_> = a.into();
466 let b: Wrapping<_> = b.into();
467
468 Value::val((a | b).0 as u64, bits)
469 }
470 InclusiveOr(a, Value::Constant(Constant { value: 0, .. })) => Ok(a),
471 InclusiveOr(Value::Constant(Constant { value: 0, .. }), b) => Ok(b),
472 InclusiveOr(_, _) => Ok(Value::Undefined),
473
474 ExclusiveOr(Value::Constant(a), Value::Constant(b)) => {
475 if a.bits != b.bits {
476 return Err(format!("tried to xor value of {} and {} bits",a.bits,b.bits).into());
477 }
478
479 let bits = a.bits;
480 let a: Wrapping<_> = a.into();
481 let b: Wrapping<_> = b.into();
482
483 Value::val((a ^ b).0 as u64, bits)
484 }
485 ExclusiveOr(_, _) => Ok(Value::Undefined),
486
487 Equal(Value::Constant(a), Value::Constant(b)) => {
488 if a.bits != b.bits {
489 return Err(format!("tried to compare value of {} and {} bits",a.bits,b.bits).into());
490 }
491
492 let a: Wrapping<_> = a.into();
493 let b: Wrapping<_> = b.into();
494
495 if a == b {
496 Value::val(1, 1)
497 } else {
498 Value::val(0, 1)
499 }
500 }
501 Equal(_, _) => Ok(Value::Undefined),
502
503 LessOrEqualUnsigned(Value::Constant(a), Value::Constant(b)) => {
504 if a.bits != b.bits {
505 return Err(format!("tried to compare value of {} and {} bits",a.bits,b.bits).into());
506 }
507
508 let a: Wrapping<_> = a.into();
509 let b: Wrapping<_> = b.into();
510
511 if a <= b {
512 Value::val(1, 1)
513 } else {
514 Value::val(0, 1)
515 }
516 }
517 LessOrEqualUnsigned(Value::Constant(Constant { value: 0, .. }), _) => Ok(Value::Constant(Constant { value: 1, bits: 1 })),
518 LessOrEqualUnsigned(_, _) => Ok(Value::Undefined),
519
520 LessOrEqualSigned(Value::Constant(a), Value::Constant(b)) => {
521 if a.bits != b.bits {
522 return Err(format!("tried to compare value of {} and {} bits",a.bits,b.bits).into());
523 }
524
525 let bits = a.bits;
526 let a: Wrapping<_> = a.into();
527 let b: Wrapping<_> = b.into();
528 let mask = Wrapping(if bits < 64 {
529 (1u64 << (bits - 1)) - 1
530 } else {
531 u64::MAX
532 });
533 let sign_mask = Wrapping(if bits < 64 { 1u64 << (bits - 1) } else { 0 });
534 if (a & sign_mask) ^ (b & sign_mask) != Wrapping(0) {
535 Value::val(if a & sign_mask != Wrapping(0) { 1 } else { 0 },1)
536 } else {
537 Value::val(if (a & mask) <= (b & mask) { 1 } else { 0 },1)
538 }
539 }
540 LessOrEqualSigned(_, _) => Ok(Value::Undefined),
541
542 LessUnsigned(Value::Constant(a), Value::Constant(b)) => {
543 if a.bits != b.bits {
544 return Err(format!("tried to compare value of {} and {} bits",a.bits,b.bits).into());
545 }
546
547 let a: Wrapping<_> = a.into();
548 let b: Wrapping<_> = b.into();
549
550 if a < b {
551 Value::val(1, 1)
552 } else {
553 Value::val(0, 1)
554 }
555 }
556 LessUnsigned(_, _) => Ok(Value::Undefined),
557
558 LessSigned(Value::Constant(a), Value::Constant(b)) => {
559 if a.bits != b.bits {
560 return Err(format!("tried to compare value of {} and {} bits",a.bits,b.bits).into());
561 }
562
563 let bits = a.bits;
564 let mut a: Wrapping<_> = a.into();
565 let mut b: Wrapping<_> = b.into();
566
567 if bits < 64 {
568 let sign_bit = Wrapping(1 << (bits - 1));
569 let m = Wrapping(1 << bits);
570
571 if sign_bit & a != Wrapping(0) {
572 a = a - m;
573 }
574 if sign_bit & b != Wrapping(0) {
575 b = b - m;
576 }
577 a = a % m;
578 b = b % m;
579 }
580
581 if a < b {
582 Value::val(1,1)
583 } else {
584 Value::val(0,1)
585 }
586 }
587 LessSigned(_, _) => Ok(Value::Undefined),
588
589 ZeroExtend(s1, Value::Constant(Constant { value: v, bits: s0 })) => {
590 let mask1 = if s1 < 64 { (1u64 << s1) - 1 } else { u64::MAX };
591 let mask0 = if s0 < 64 { (1u64 << s0) - 1 } else { u64::MAX };
592 Value::val((v & mask0) & mask1,s1)
593 }
594 ZeroExtend(s, Value::Variable(Variable { name, .. })) => {
595 Value::var(name,s)
596 }
597 ZeroExtend(_, Value::Undefined) => Ok(Value::Undefined),
598
599 SignExtend(t, Value::Constant(Constant { value: v, bits: s })) => {
600 let mask0 = if s < 64 { (1u64 << s) - 1 } else { u64::MAX };
601 let mask1 = if t < 64 { (1u64 << t) - 1 } else { u64::MAX };
602 let sign = if s < 64 { 1u64 << (s - 1) } else { 0 };
603
604 if v & sign == 0 {
605 Value::val((v & mask0) & mask1, t)
606 } else {
607 let mask = mask1 & !mask0;
608 Value::val((v & mask0) | mask, t)
609 }
610 }
611 SignExtend(s, Value::Variable(Variable { name, .. })) => {
612 Value::var(name,s)
613 }
614 SignExtend(_, Value::Undefined) => Ok(Value::Undefined),
615
616 Move(a) => Ok(a),
617
618 Initialize(_, _) => Ok(Value::Undefined),
619
620 Select(off, sz, Value::Constant(a)) => {
621 let Constant{ value: a_value, bits: a_bits } = a;
622
623 if off + sz < 64 && a_bits <= off + sz {
624 let val = a_value >> off;
625 let mask = (1 << sz) - 1;
626
627 Value::val(val & mask, sz)
628 } else {
629 Ok(Value::Undefined)
630 }
631 }
632 Select(_, _, _) => Ok(Value::Undefined),
633 Assume(_, _) => Ok(Value::Undefined),
634
635 Load(_, _, _, _) => Ok(Value::Undefined),
636
637 Phi(ref a@Value::Variable(_),Value::Undefined,Value::Undefined) => Ok(a.clone()),
638 Phi(ref a@Value::Variable(_),ref b@Value::Variable(_),Value::Undefined) if *a == *b => Ok(a.clone()),
639 Phi(ref a@Value::Variable(_),ref b@Value::Variable(_),ref c@Value::Variable(_)) if *a == *b && *b == *c => Ok(a.clone()),
640 Phi(_,_,_) => Ok(Value::Undefined),
641 }
642 }
643}
644
645impl Arbitrary for Operation {
646 fn arbitrary<G: Gen>(g: &mut G) -> Self {
647 loop {
648 let op = match g.gen_range(0, 26) {
649 0 => Operation::Add(Value::arbitrary(g), Value::arbitrary(g)),
650 1 => Operation::Subtract(Value::arbitrary(g), Value::arbitrary(g)),
651 2 => Operation::Multiply(Value::arbitrary(g), Value::arbitrary(g)),
652 3 => Operation::DivideUnsigned(Value::arbitrary(g), Value::arbitrary(g)),
653 4 => Operation::DivideSigned(Value::arbitrary(g), Value::arbitrary(g)),
654 5 => Operation::ShiftLeft(Value::arbitrary(g), Value::arbitrary(g)),
655 6 => Operation::ShiftRightUnsigned(Value::arbitrary(g), Value::arbitrary(g)),
656 7 => Operation::ShiftRightSigned(Value::arbitrary(g), Value::arbitrary(g)),
657 8 => Operation::Modulo(Value::arbitrary(g), Value::arbitrary(g)),
658 9 => Operation::And(Value::arbitrary(g), Value::arbitrary(g)),
659 10 => Operation::InclusiveOr(Value::arbitrary(g), Value::arbitrary(g)),
660 11 => Operation::ExclusiveOr(Value::arbitrary(g), Value::arbitrary(g)),
661
662 12 => Operation::Equal(Value::arbitrary(g), Value::arbitrary(g)),
663 13 => Operation::LessOrEqualUnsigned(Value::arbitrary(g), Value::arbitrary(g)),
664 14 => Operation::LessOrEqualSigned(Value::arbitrary(g), Value::arbitrary(g)),
665 15 => Operation::LessUnsigned(Value::arbitrary(g), Value::arbitrary(g)),
666 16 => Operation::LessSigned(Value::arbitrary(g), Value::arbitrary(g)),
667
668 17 => Operation::ZeroExtend(g.gen(), Value::arbitrary(g)),
669 18 => Operation::SignExtend(g.gen(), Value::arbitrary(g)),
670
671 19 => Operation::Move(Value::arbitrary(g)),
672 20 => Operation::Initialize(StrRef::arbitrary(g),g.gen()),
673
674 21 => {
675 let v = Value::arbitrary(g);
676 let off = g.gen_range(0, v.bits().unwrap_or(0) + 1);
677 let sz = g.gen_range(0, v.bits().unwrap_or(0) + 1 - off);
678 Operation::Select(off, sz, v)
679 }
680 22 => Operation::Assume(Constraint::arbitrary(g), Value::arbitrary(g)),
681
682 23 => Operation::Load(Segment::arbitrary(g), Endianess::arbitrary(g), g.gen(), Value::arbitrary(g)),
683
684 24 => {
685 let a = Value::arbitrary(g);
687 let b = Value::arbitrary(g);
688 Operation::Phi(a,b,Value::undef())
689 }
690 25 => {
691 let a = Value::arbitrary(g);
692 let b = Value::arbitrary(g);
693 let c = Value::arbitrary(g);
694 Operation::Phi(a,b,c)
695 }
696
697 _ => unreachable!(),
698 };
699
700 match op {
701 Operation::Add(Value::Undefined, Value::Undefined) => {}
702 Operation::Subtract(Value::Undefined, Value::Undefined) => {}
703 Operation::Multiply(Value::Undefined, Value::Undefined) => {}
704 Operation::DivideUnsigned(Value::Undefined, Value::Undefined) => {}
705 Operation::DivideSigned(Value::Undefined, Value::Undefined) => {}
706 Operation::Modulo(Value::Undefined, Value::Undefined) => {}
707 Operation::ShiftLeft(Value::Undefined, Value::Undefined) => {}
708 Operation::ShiftRightUnsigned(Value::Undefined, Value::Undefined) => {}
709 Operation::ShiftRightSigned(Value::Undefined, Value::Undefined) => {}
710 Operation::And(Value::Undefined, Value::Undefined) => {}
711 Operation::InclusiveOr(Value::Undefined, Value::Undefined) => {}
712 Operation::ExclusiveOr(Value::Undefined, Value::Undefined) => {}
713 Operation::Equal(Value::Undefined, Value::Undefined) => {}
714 Operation::LessOrEqualUnsigned(Value::Undefined, Value::Undefined) => {}
715 Operation::LessOrEqualSigned(Value::Undefined, Value::Undefined) => {}
716 Operation::LessUnsigned(Value::Undefined, Value::Undefined) => {}
717 Operation::LessSigned(Value::Undefined, Value::Undefined) => {}
718 Operation::ZeroExtend(_, Value::Undefined) => {}
719 Operation::SignExtend(_, Value::Undefined) => {}
720 Operation::Select(_, _, Value::Undefined) => {}
721 Operation::Phi(Value::Undefined, _, _) => {}
722 Operation::Phi(_, Value::Undefined, _) => {}
723 Operation::Phi(_, Value::Constant(_), _) => {}
724 Operation::Phi(_, _, Value::Constant(_)) => {}
725
726 _ => { return op; }
727 }
728 }
729 }
730}
731
732#[derive(Clone,PartialEq,Eq,Debug,Hash)]
734pub enum CallTarget {
735 Function(UUID),
737 External(Str),
739}
740
741#[derive(Clone,PartialEq,Eq,Debug)]
743pub enum MemoryOperation {
744 Store{
746 segment: Segment,
748 endianess: Endianess,
750 bytes: usize,
752 address: Value,
754 value: Value,
756 },
757
758 MemoryPhi(Option<Segment>,Option<Segment>,Option<Segment>),
760
761 Allocate{
763 base: StrRef,
765 }
766}
767
768#[derive(Clone,PartialEq,Eq,Debug)]
770pub enum FlowOperation {
771 Call{
773 function: UUID,
775 },
776 ExternalCall{
778 external: StrRef,
780 },
781 IndirectCall{
783 target: Variable,
785 },
786 Return,
788}
789
790#[derive(Clone,PartialEq,Eq,Debug)]
792pub enum Statement {
793 Expression{
795 result: Variable,
797 op: Operation,
799 },
800 Flow{
802 op: FlowOperation,
804 },
805 Memory{
807 op: MemoryOperation,
809 result: Segment,
811 },
812}
813
814impl Statement {
815 pub fn sanity_check(&self) -> Result<()> {
820 use std::cmp;
821 use errors::ResultExt;
822
823 let typecheck_binop = |a: &Value, b: &Value, result: &Variable| -> Result<()> {
825 if !(a.bits() == None || b.bits() == None || a.bits() == b.bits()) {
826 return Err(format!("Argument sizes mismatch: {:?} vs. {:?}", a, b).into());
827 }
828
829 if cmp::max(a.bits().unwrap_or(0), b.bits().unwrap_or(0)) != result.bits {
830 return Err(format!("Operation result and result sizes mismatch ({:?})",self).into());
831 }
832
833 Ok(())
834 };
835 let typecheck_cmpop = |a: &Value, b: &Value, result: &Variable| -> Result<()> {
836 if !(a.bits() == None || b.bits() == None || a.bits() == b.bits()) {
837 return Err("Argument sizes mismatch".into());
838 }
839
840 if result.bits != 1 {
841 return Err("Compare operation result not a flag".into());
842 }
843
844 Ok(())
845 };
846 let typecheck_unop = |a: &Value, sz: Option<usize>, result: &Variable| -> Result<()> {
847 if sz.is_none() {
848 if !(a.bits() == None || Some(result.bits) <= a.bits()) {
850 return Err("Operation result and result sizes mismatch".into());
851 }
852 } else {
853 if !(a.bits() == None || Some(result.bits) == sz) {
854 return Err("Operation result and result sizes mismatch".into());
855 }
856 }
857 Ok(())
858 };
859
860 match self {
861 &Statement::Expression { op: Operation::Add(ref a, ref b), ref result } => typecheck_binop(a, b, result),
862 &Statement::Expression { op: Operation::Subtract(ref a, ref b), ref result } => typecheck_binop(a, b, result),
863 &Statement::Expression { op: Operation::Multiply(ref a, ref b), ref result } => typecheck_binop(a, b, result),
864 &Statement::Expression { op: Operation::DivideUnsigned(ref a, ref b), ref result } => typecheck_binop(a, b, result),
865 &Statement::Expression { op: Operation::DivideSigned(ref a, ref b), ref result } => typecheck_binop(a, b, result),
866 &Statement::Expression { op: Operation::ShiftLeft(ref a, ref b), ref result } => typecheck_binop(a, b, result),
867 &Statement::Expression {
868 op: Operation::ShiftRightUnsigned(ref a, ref b),
869 ref result,
870 } => typecheck_binop(a, b, result),
871 &Statement::Expression { op: Operation::ShiftRightSigned(ref a, ref b), ref result } => typecheck_binop(a, b, result),
872 &Statement::Expression { op: Operation::Modulo(ref a, ref b), ref result } => typecheck_binop(a, b, result),
873 &Statement::Expression { op: Operation::And(ref a, ref b), ref result } => typecheck_binop(a, b, result),
874 &Statement::Expression { op: Operation::ExclusiveOr(ref a, ref b), ref result } => typecheck_binop(a, b, result),
875 &Statement::Expression { op: Operation::InclusiveOr(ref a, ref b), ref result } => typecheck_binop(a, b, result),
876
877 &Statement::Expression { op: Operation::Equal(ref a, ref b), ref result } => typecheck_cmpop(a, b, result),
878 &Statement::Expression {
879 op: Operation::LessOrEqualUnsigned(ref a, ref b),
880 ref result,
881 } => typecheck_cmpop(a, b, result),
882 &Statement::Expression { op: Operation::LessOrEqualSigned(ref a, ref b), ref result } => typecheck_cmpop(a, b, result),
883 &Statement::Expression { op: Operation::LessUnsigned(ref a, ref b), ref result } => typecheck_cmpop(a, b, result),
884 &Statement::Expression { op: Operation::LessSigned(ref a, ref b), ref result } => typecheck_cmpop(a, b, result),
885
886 &Statement::Expression { op: Operation::SignExtend(ref a, ref b), ref result } => typecheck_unop(b, Some(*a), result),
887 &Statement::Expression { op: Operation::ZeroExtend(ref a, ref b), ref result } => typecheck_unop(b, Some(*a), result),
888 &Statement::Expression { op: Operation::Move(ref a), ref result } => typecheck_unop(a, None, result),
889 &Statement::Expression { op: Operation::Select(off, sz, ref a), ref result } => {
890 if !(result.bits == sz && off + sz <= a.bits().unwrap_or(off + sz)) {
891 Err("Ill-sized Select operation".into())
892 } else {
893 Ok(())
894 }
895 }
896
897 &Statement::Expression{ op: Operation::Initialize(_,ref sz), ref result } => {
898 if result.bits != *sz {
899 Err("Operation result and result sizes mismatch".into())
900 } else {
901 Ok(())
902 }
903 }
904
905 _ => { Ok(()) }
950 }.chain_err(|| format!("Failed sanity check for {:?}", self))?;
951
952 Ok(())
953 }
954}
955
956impl Arbitrary for Statement {
957 fn arbitrary<G: Gen>(g: &mut G) -> Self {
958 loop {
959 let stmt = match g.gen_range(0, 7) {
960 0 => Statement::Expression{
961 result: Variable::arbitrary(g),
962 op: Operation::arbitrary(g),
963 },
964 1 => Statement::Flow{ op: FlowOperation::Call{ function: UUID::arbitrary(g) }, },
965 2 => Statement::Flow{ op: FlowOperation::ExternalCall{ external: StrRef::arbitrary(g) }, },
966 3 => Statement::Flow{ op: FlowOperation::IndirectCall{ target: Variable::arbitrary(g) }, },
967 4 => Statement::Flow{ op: FlowOperation::Return },
968 5 => {
969 let mut addr = Value::arbitrary(g);
970 let mut val = Value::arbitrary(g);
971
972 while addr == Value::Undefined && val == Value::Undefined {
973 addr = Value::arbitrary(g);
974 val = Value::arbitrary(g);
975 }
976
977 Statement::Memory{
978 op: MemoryOperation::Store{
979 segment: Segment::arbitrary(g),
980 endianess: Endianess::arbitrary(g),
981 bytes: g.gen_range(1,11),
982 address: addr,
983 value: val,
984 },
985 result: Segment::arbitrary(g),
986 }
987 }
988 6 => {
989 let op = match g.gen_range(0,4) {
990 0 => MemoryOperation::MemoryPhi(
991 None,
992 None,
993 None),
994 1 => MemoryOperation::MemoryPhi(
995 Some(Segment::arbitrary(g)),
996 None,
997 None),
998 2 => MemoryOperation::MemoryPhi(
999 Some(Segment::arbitrary(g)),
1000 Some(Segment::arbitrary(g)),
1001 None),
1002 3 => MemoryOperation::MemoryPhi(
1003 Some(Segment::arbitrary(g)),
1004 Some(Segment::arbitrary(g)),
1005 Some(Segment::arbitrary(g))),
1006 _ => unreachable!(),
1007 };
1008
1009 Statement::Memory{
1010 op: op,
1011 result: Segment::arbitrary(g),
1012 }
1013 }
1014 _ => unreachable!(),
1015 };
1016
1017 if stmt.sanity_check().is_ok() {
1018 return stmt;
1019 }
1020 }
1021 }
1022}
1023
1024#[macro_export]
1025macro_rules! rreil2 {
1026 ( ( $names:tt , $segs:tt ) { } ) => {Ok(vec![])};
1027 ( ( $names:tt , $segs:tt ) { add $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # Add # $($cdr)*) };
1028 ( ( $names:tt , $segs:tt ) { sub $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # Subtract # $($cdr)*) };
1029 ( ( $names:tt , $segs:tt ) { mul $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # Multiply # $($cdr)*) };
1030 ( ( $names:tt , $segs:tt ) { div $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # DivideUnsigned # $($cdr)*) };
1031 ( ( $names:tt , $segs:tt ) { divs $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # DivideSigned # $($cdr)*) };
1032 ( ( $names:tt , $segs:tt ) { shl $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # ShiftLeft # $($cdr)*) };
1033 ( ( $names:tt , $segs:tt ) { shr $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # ShiftRightUnsigned # $($cdr)*) };
1034 ( ( $names:tt , $segs:tt ) { shrs $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # ShiftRightSigned # $($cdr)*) };
1035 ( ( $names:tt , $segs:tt ) { mod $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # Modulo # $($cdr)*) };
1036 ( ( $names:tt , $segs:tt ) { and $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # And # $($cdr)*) };
1037 ( ( $names:tt , $segs:tt ) { xor $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # ExclusiveOr # $($cdr)*) };
1038 ( ( $names:tt , $segs:tt ) { or $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # InclusiveOr # $($cdr)*) };
1039
1040 ( ( $names:tt , $segs:tt ) { cmpeq $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # Equal # $($cdr)*) };
1041 ( ( $names:tt , $segs:tt ) { cmpleu $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # LessOrEqualUnsigned # $($cdr)*) };
1042 ( ( $names:tt , $segs:tt ) { cmples $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # LessOrEqualSigned # $($cdr)*) };
1043 ( ( $names:tt , $segs:tt ) { cmpltu $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # LessUnsigned # $($cdr)*) };
1044 ( ( $names:tt , $segs:tt ) { cmplts $($cdr:tt)* } ) => { rreil2_binop!($names # $segs # LessSigned # $($cdr)*) };
1045
1046 ( ( $names:tt , $segs:tt ) { sel / $off:tt / $sz:tt $($cdr:tt)* } ) => { rreil2_selop!($names # $segs # Select # $off # $sz # $($cdr)*) };
1047 ( ( $names:tt , $segs:tt ) { sext / $sz:tt $($cdr:tt)* } ) => { rreil2_extop!($names # $segs # SignExtend # $sz # $($cdr)*) };
1048 ( ( $names:tt , $segs:tt ) { zext / $sz:tt $($cdr:tt)* } ) => { rreil2_extop!($names # $segs # ZeroExtend # $sz # $($cdr)*) };
1049 ( ( $names:tt , $segs:tt ) { mov $($cdr:tt)* } ) => { rreil2_unop!($names # $segs # Move # $($cdr)*) };
1050 ( ( $names:tt , $segs:tt ) { call $($cdr:tt)* } ) => { rreil2_callop!($names # $segs # $($cdr)*) };
1051 ( ( $names:tt , $segs:tt ) { ret $($cdr:tt)* } ) => { rreil2_retop!($names # $segs # $($cdr)*) };
1052
1053 ( ( $names:tt , $segs:tt ) { load / $r:ident / $en:ident / $sz:tt $($cdr:tt)* } ) => { rreil_load!($names # $segs # $r # $en # $sz # $($cdr)*) };
1054 ( ( $names:tt , $segs:tt ) { store / $r:ident / $en:ident / $sz:tt $($cdr:tt)* } ) => { rreil_store!($names # $segs # $r # $en # $sz # $($cdr)*) };
1055}
1056
1057include!(concat!(env!("OUT_DIR"), "/rreil.rs"));
1058
1059#[macro_export]
1060macro_rules! rreil_var {
1061 ( $names:tt # ( $a:expr ) ) =>
1062 { ($a).clone().into() };
1063 ( $names:tt # $a:ident : $a_w:tt ) => {
1064 $crate::Variable{
1065 name: $names.insert(&$crate::Name::new(stringify!($a).into(),None)),
1066 bits: rreil_imm!($a_w)
1067 }
1068 };
1069}
1070
1071#[macro_export]
1072macro_rules! rreil_val {
1073 ( $names:tt # ? ) => { $crate::Value::Undefined };
1074 ( $names:tt # ( $a:expr ) ) => { ($a).clone().into() };
1075 ( $names:tt # [ $a:tt ] : $a_w:tt ) => {
1076 $crate::Value::Constant($crate::Constant{
1077 value: rreil_imm!($a) as u64,
1078 bits: rreil_imm!($a_w)
1079 })
1080 };
1081 ( $names:tt # $a:ident : $a_w:tt ) => {
1082 $crate::Value::Variable($crate::Variable{
1083 name: $names.insert(&$crate::Name::new(stringify!($a).into(),None)),
1084 bits: rreil_imm!($a_w)
1085 })
1086 };
1087}
1088
1089#[macro_export]
1090macro_rules! rreil_imm {
1091 ($x:expr) => ($x as usize);
1092}
1093
1094#[cfg(test)]
1095mod tests {
1096 use super::*;
1097 use {Value};
1098
1099 #[test]
1100 fn rreil_macro() {
1101 use {Name,Names,Segments};
1102
1103 let mut names = Names::default();
1104 let mut segs = Segments::default();
1105 let eax = Value::var(names.insert(&Name::new("eax".into(),None)),12).unwrap();
1106 let t0 = Variable::new(names.insert(&Name::new("eax".into(),None)),12).unwrap();
1107 let val = Value::val(1337,12).unwrap();
1108
1109 let _ = rreil2!{
1110 (names,segs) {
1111 add (t0), (val), (eax);
1112 and t0:32, [2147483648]:32, eax:32;
1113 and t1:32, [2147483648]:32, ebx:32;
1114 sub t2:32, ebx : 32 , eax:32;
1115 and t3:32, [2147483648]:32, t2:32;
1116 shr SF:8, [31]:8, t3:8;
1117 xor t4:32, t1:32, t0:32;
1118 xor t5:32, t3:32, t0:32;
1119 and t6:32, t5:32, t4:32;
1120 shr OF:8, [31]:8, t6:8;
1121 and t7:64, [4294967296]:64, t2:64;
1122 shr CF:8, [32]:8, t7:8;
1123 and t8:32, [4294967295]:32, t2:32;
1124 xor t9:8, OF:8, SF:8;
1125 sel/0/32 ebx:32, rax:64;
1126 }
1127 }.unwrap();
1128
1129 let _ = rreil2!{
1130 (names,segs) {
1131 sub t0:32, eax:32, ebx:32;
1132 cmpltu CF:1, eax:32, ebx:32;
1133 cmpleu CForZF:1, eax:32, ebx:32;
1134 cmplts SFxorOF:1, eax:32, ebx:32;
1135 cmples SFxorOForZF:1, eax:32, ebx:32;
1136 cmpeq ZF:1, eax:32, ebx:32;
1137 cmplts SF:1, t0:32, [0]:32;
1138 xor OF:1, SFxorOF:1, SF:1;
1139 }
1140 }.unwrap();
1141
1142 let _ = rreil2!{
1143 (names,segs) {
1144 sub rax:32, rax:32, [1]:32;
1145 mov rax:32, [0]:32;
1146 }
1147 }.unwrap();
1148
1149 let _ = rreil2!{
1150 (names,segs) {
1151 store/ram/le/32 rax:32, [0]:32;
1152 load/ram/le/32 rax:32, [0]:32;
1153 }
1154 }.unwrap();
1155
1156 let _ = rreil2!{
1157 (names,segs) {
1158 sext/32 rax:32, ax:16;
1159 zext/32 rax:32, ax:16;
1160 mov rax:32, tbx:32;
1161 }
1162 };
1163 }
1164}