p8n_types/
il.rs

1// Panopticon - A libre program analysis library for machine code
2// Copyright (C) 2014-2018  The Panopticon Developers
3//
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8//
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12// Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17
18use 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/// Address range with sub-byte pecision. Used to order instructions that don't occupy any space in
31/// the binary (e.g. Phi).
32#[derive(Clone,PartialEq,Eq)]
33pub struct Area {
34    /// First byte (inclusive).
35    pub start: u64,
36    /// Last byte (exclusive).
37    pub end: u64,
38    /// Logic order inside the first byte (inclusive).
39    pub offset_start: usize,
40    /// Logic order inside the last byte (exclusive).
41    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/// Byte order.
71#[derive(Debug,Clone,Copy,PartialEq,Eq)]
72pub enum Endianess {
73    /// Least significant byte first.
74    Little,
75    /// Most significant byte first.
76    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/// A RREIL operation.
90#[derive(Clone,PartialEq,Eq,Debug)]
91pub enum Operation {
92    /// Integer addition
93    Add(Value, Value),
94    /// Integer subtraction
95    Subtract(Value, Value),
96    /// Unsigned integer multiplication
97    Multiply(Value, Value),
98    /// Unsigned integer division
99    DivideUnsigned(Value, Value),
100    /// Signed integer division
101    DivideSigned(Value, Value),
102    /// Bitwise left shift
103    ShiftLeft(Value, Value),
104    /// Bitwise logical right shift
105    ShiftRightUnsigned(Value, Value),
106    /// Bitwise arithmetic right shift
107    ShiftRightSigned(Value, Value),
108    /// Integer modulo
109    Modulo(Value, Value),
110    /// Bitwise logical and
111    And(Value, Value),
112    /// Bitwise logical or
113    InclusiveOr(Value, Value),
114    /// Bitwise logical xor
115    ExclusiveOr(Value, Value),
116
117    /// Compare both operands for equality and returns `1` or `0`
118    Equal(Value, Value),
119    /// Returns `1` if the first operand is less than or equal to the second and `0` otherwise.
120    /// Comparison assumes unsigned values.
121    LessOrEqualUnsigned(Value, Value),
122    /// Returns `1` if the first operand is less than or equal to the second and `0` otherwise.
123    /// Comparison assumes signed values.
124    LessOrEqualSigned(Value, Value),
125    /// Returns `1` if the first operand is less than the second and `0` otherwise.
126    /// Comparison assumes unsigned values.
127    LessUnsigned(Value, Value),
128    /// Returns `1` if the first operand is less than the second and `0` otherwise.
129    /// Comparison assumes signed values.
130    LessSigned(Value, Value),
131
132    /// Zero extends the operand.
133    ZeroExtend(usize, Value),
134    /// Sign extends the operand.
135    SignExtend(usize, Value),
136    /// Copies the operand without modification.
137    Move(Value),
138    /// Initializes a global variable.
139    Initialize(StrRef,usize),
140    /// Copies only the range [self.0, self.0 + self.1] of bits from the operand.
141    Select(usize, usize, Value),
142    /// Asserts that the second operand is constraint by the first.
143    Assume(Constraint,Value),
144    /// Reads a memory cell
145    Load(Segment,Endianess,usize,Value),
146
147    /// SSA Phi function
148    Phi(Value,Value,Value),
149}
150
151impl Operation {
152    /// Returns references values that are read by the operation.
153    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    /// Returns mutables references values that are read by the operation.
196    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    /// Executes a RREIL operation returning the result.
239    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                    // XXX: make sizes equal?
686                    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/// Things that can be called.
733#[derive(Clone,PartialEq,Eq,Debug,Hash)]
734pub enum CallTarget {
735    /// A known, analysied function.
736    Function(UUID),
737    /// An external, unknown function.
738    External(Str),
739}
740
741/// A memory operation.
742#[derive(Clone,PartialEq,Eq,Debug)]
743pub enum MemoryOperation {
744    /// Writes a memory cell
745    Store{
746        /// Memory segment before the store.
747        segment: Segment,
748        /// Byte order if `bytes` > 1
749        endianess: Endianess,
750        /// Number of bytes to be written.
751        bytes: usize,
752        /// Address inside `segment` written to.
753        address: Value,
754        /// Value that is written.
755        value: Value,
756    },
757
758    /// Memory phi. Merges up to three memory segments.
759    MemoryPhi(Option<Segment>,Option<Segment>,Option<Segment>),
760
761    /// Introduces a new memory segment into the function context.
762    Allocate{
763        /// Segment base name.
764        base: StrRef,
765    }
766}
767
768/// Call/Return operations.
769#[derive(Clone,PartialEq,Eq,Debug)]
770pub enum FlowOperation {
771    /// Function call.
772    Call{
773        /// Function call target.
774        function: UUID,
775    },
776    /// Call to an imported function.
777    ExternalCall{
778        /// Name of the imported function.
779        external: StrRef,
780    },
781    /// Call to an unknown value.
782    IndirectCall{
783        /// Call target
784        target: Variable,
785    },
786    /// Return.
787    Return,
788}
789
790/// A single IL statement.
791#[derive(Clone,PartialEq,Eq,Debug)]
792pub enum Statement {
793    /// A single RREIL statement.
794    Expression{
795        /// Value that the operation result is assigned to
796        result: Variable,
797        /// Operation and its arguments
798        op: Operation,
799    },
800    /// Interprocedural control flow operation
801    Flow{
802        /// Operation
803        op: FlowOperation,
804    },
805    /// A memory operation
806    Memory{
807        /// Operation
808        op: MemoryOperation,
809        /// Memory segment resulting from the memory operation.
810        result: Segment,
811    },
812}
813
814impl Statement {
815    /// Does a simple sanity check. The functions returns Err if
816    /// - The argument size are not equal
817    /// - The result has not the same size as `assignee`
818    /// - The select operation arguments are out of range
819    pub fn sanity_check(&self) -> Result<()> {
820        use std::cmp;
821        use errors::ResultExt;
822
823        // check that argument sizes match
824        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                // zext?
849                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            /*
906            &Statement::Expression { op: Operation::Call(_), ref result } => {
907                if !(result == &Lvalue::Undefined) {
908                    return Err("Call operation can only be assigned to Undefined".into());
909                } else {
910                    Ok(())
911                }
912            }
913
914            &Statement::Expression{ op: Operation::Load(_,_,ref sz,_), ref result } => {
915                if !result.bits.is_none() && result.bits != Some(*sz) {
916                    return Err(format!("Memory operation with invalid size. Expected {:?} got {:?}",Some(*sz),result.bits).into());
917                } else if *sz == 0 {
918                    return Err("Memory operation of size 0".into());
919                } else if *sz % 8 != 0 {
920                    return Err("Memory operation not byte aligned".into());
921                } else {
922                    Ok(())
923                }
924            }
925
926            &Statement::Expression{ op: Operation::Store(_,_,sz,_,ref val), ref result } => {
927                if val.bits().is_some() && result.bits.is_some() && val.bits() != result.bits {
928                    return Err("Memory store value with inconsitend size".into());
929                } else if sz == 0 {
930                    return Err("Memory operation of size 0".into());
931                } else if val.bits().is_some() && val.bits() != Some(sz) {
932                    return Err(format!("Memory store value with inconsitend size: {:?} != {}",val.bits(),sz).into());
933                } else if sz % 8 != 0 {
934                    return Err("Memory operation not byte aligned".into());
935                } else {
936                    Ok(())
937                }
938            }
939
940
941            &Statement::Expression { op: Operation::Phi(ref vec), ref result } => {
942                if !(vec.iter().all(|rv| rv.bits() == result.bits) && result.bits != None) {
943                    return Err("Phi arguments must have equal sizes and can't be Undefined".into());
944                } else {
945                    Ok(())
946                }
947            }
948            */
949            _ => { 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}