p8n_types/
value.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::num::Wrapping;
19use std::u64;
20
21use quickcheck::{Arbitrary,Gen};
22
23use {NameRef,Result,SegmentRef};
24
25/// A variable with known size.
26#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Debug,Hash)]
27pub struct Variable {
28    /// Name of the variable.
29    pub name: NameRef,
30    /// Size of the variable value in bits. Never zero.
31    pub bits: usize,
32}
33
34impl Variable {
35    /// Crates a new variable. Fails if `bits` zero.
36    pub fn new(name: NameRef, bits: usize) -> Result<Variable> {
37        if bits == 0 { return Err("Variable can't have size 0".into()); }
38
39        Ok(Variable{
40            name: name,
41            bits: bits
42        })
43    }
44}
45
46/// A constant value.
47#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Debug,Hash)]
48pub struct Constant {
49    /// Value
50    pub value: u64,
51    /// Size of the value in bits. Never zero.
52    pub bits: usize,
53}
54
55impl Constant {
56    /// Create a new constant. Fails if `bits` is zero.
57    pub fn new(value: u64, bits: usize) -> Result<Constant> {
58        if bits == 0 { return Err("Variable can't have size 0".into()); }
59
60        Ok(Constant{
61            value: value,
62            bits: bits
63        })
64    }
65
66    /// Returns a bit mask covering all bits of the constant. Returns `u64::MAX` if `bits` > 64.
67    pub fn mask(&self) -> Wrapping<u64> {
68        Wrapping(if self.bits < 64 { (1u64 << self.bits) - 1 } else { u64::MAX })
69    }
70}
71
72impl Into<Wrapping<u64>> for Constant {
73    fn into(self) -> Wrapping<u64> {
74        Wrapping(self.value) & self.mask()
75    }
76}
77
78/// A RREIL value.
79#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Debug,Hash)]
80pub enum Value {
81    /// An undefined value of unknown size.
82    Undefined,
83    /// A RREIL variable, possibly in SSA form.
84    Variable(Variable),
85    /// A constant value.
86    Constant(Constant),
87}
88
89impl Value {
90    /// Creates a new constant value. Fails if `bits` is zero.
91    pub fn val(val: u64, bits: usize) -> Result<Value> {
92        Ok(Value::Constant(Constant::new(val,bits)?))
93    }
94
95    /// Creates a new variable. Fails if `bits` is zero.
96    pub fn var(name: NameRef, bits: usize) -> Result<Value> {
97        Ok(Value::Variable(Variable::new(name,bits)?))
98    }
99
100    /// Creates an undefined value.
101    pub fn undef() -> Value {
102        Value::Undefined
103    }
104
105    /// Returns the size of the value in bits or `None` if it is the undefined value.
106    pub fn bits(&self) -> Option<usize> {
107        match self {
108            &Value::Variable(Variable{ bits,.. }) => Some(bits),
109            &Value::Constant(Constant{ bits,.. }) => Some(bits),
110            &Value::Undefined => None,
111        }
112    }
113
114
115}
116
117impl From<Variable> for Value {
118    fn from(v: Variable) -> Value {
119        Value::Variable(v)
120    }
121}
122
123impl From<Constant> for Value {
124    fn from(v: Constant) -> Value {
125        Value::Constant(v)
126    }
127}
128
129/// A RREIL memory segment identifier.
130#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
131pub struct Segment {
132    /// Segment name.
133    pub name: SegmentRef,
134}
135
136impl Arbitrary for Variable {
137    fn arbitrary<G: Gen>(g: &mut G) -> Self {
138        Variable {
139            name: NameRef::arbitrary(g),
140            bits: 1 << g.gen_range(0, 11),
141        }
142    }
143}
144
145impl Arbitrary for Constant {
146    fn arbitrary<G: Gen>(g: &mut G) -> Self {
147        Constant{
148            value: g.gen(),
149            bits: 1 << g.gen_range(0, 11),
150        }
151    }
152}
153
154impl Arbitrary for Segment {
155    fn arbitrary<G: Gen>(g: &mut G) -> Self {
156        Segment{ name: SegmentRef::new(g.gen_range(0,100)) }
157    }
158}
159
160impl Arbitrary for Value {
161    fn arbitrary<G: Gen>(g: &mut G) -> Self {
162        match g.gen_range(0, 2) {
163            0 => Value::Undefined,
164            1 => Value::Variable(Variable::arbitrary(g)),
165            2 => Value::Constant(Constant::arbitrary(g)),
166            _ => unreachable!(),
167        }
168    }
169}