p8n_types/
mnemonic.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::usize;
19
20use smallvec::SmallVec;
21
22use {Area,Function,StrRef,Value};
23
24/// Native ISA mnemonic.
25#[derive(Clone,Debug,PartialEq,Eq)]
26pub struct Mnemonic {
27    /// Addresses this mnemonic occupies.
28    pub area: Area,
29    /// Disassembled opcode.
30    pub opcode: StrRef,
31    /// Arguments, in and out.
32    pub operands: SmallVec<[Value; 3]>,
33    /// Number of IL statements used to model its semantics.
34    pub statement_count: usize,
35}
36
37impl Mnemonic {
38    /// Create a new argument and IL-statement less mnemonic.
39    pub fn new(a: Area, s: StrRef) -> Mnemonic {
40        Mnemonic{
41            area: a,
42            opcode: s,
43            operands: SmallVec::default(),
44            statement_count: 0,
45        }
46    }
47}
48
49/*
50/// Internal to `Mnemonic`
51#[derive(Clone,Debug)]
52pub enum Argument {
53    /// Internal to `Mnemonic`
54    Literal(StrRef),
55    /// Internal to `Mnemonic`
56    Value {
57        /// Internal to `Mnemonic`
58        has_sign: bool,
59        /// Internal to `Mnemonic`
60        value: Value,
61    },
62    /// Internal to `Mnemonic`
63    Pointer {
64        /// Internal to `Mnemonic`
65        is_code: bool,
66        /// Internal to `Mnemonic`
67        region: StrRef,
68        /// Internal to `Mnemonic`
69        address: Value,
70    },
71}
72
73macro_rules! arg {
74    ( { u : $val:expr } $cdr:tt ) => {
75        Argument::Value{
76            has_sign: false,
77            value: ($val).into(),
78        }
79    }
80    ( { s : $val:expr } $cdr:tt ) => {
81        Argument::Value{
82            has_sign: true,
83            value: ($val).into(),
84        }
85    }
86    ( { p : $val:expr : $bank:expr } $cdr:tt ) => {
87        Argument::Pointer{
88            is_code: false,
89            region: ($bank).into(),
90            address: ($val).into(),
91        }
92    }
93    ( { c : $val:expr : $bank:expr } $cdr:tt ) => {
94        Argument::Pointer{
95            is_code: false,
96            region: ($bank).into(),
97            address: ($val).into(),
98        }
99    }
100    ( ) => {}
101}
102
103arg!({ u : Variable::new("test",1,None) } "sss");
104arg!({ s : Variable::new("test",1,None) } "sss");
105
106impl Argument {
107    /// format := '{' type '}'
108    /// type := 'u' ':' value | # unsigned
109    ///         's' ':' value | # signed
110    ///         'p' ':' value ':' bank |  # data pointer
111    ///         'c' ':' value ':' bank |  # code pointer
112    /// value := digit+ | xdigit+ | # constant
113    ///          alpha alphanum* | # variable
114    /// bank := alpha alphanum*
115     pub fn parse(mut j: Chars) -> Result<Vec<Argument>> {
116        named!(main, tag!("{"
117*/
118
119/// Index of a mnemonic in a function. Local to a specific function.
120#[derive(Clone,Copy,Debug,PartialOrd,Ord,PartialEq,Eq)]
121pub struct MnemonicIndex {
122    index: usize
123}
124
125impl MnemonicIndex {
126    /// Create a new MnemonicIndex for the `i`th mnemonic.
127    pub fn new(i: usize) -> MnemonicIndex { MnemonicIndex{ index: i } }
128
129    /// Returns the numeric index of this mnemonic. Can be used for arthimetic.
130    pub fn index(&self) -> usize { self.index }
131}
132
133/// Iterator over a range of mnemonics
134#[derive(Clone)]
135pub struct MnemonicIterator<'a> {
136    function: &'a Function,
137    index: usize,
138    max: usize,
139}
140
141impl<'a> MnemonicIterator<'a> {
142    /// Creates a new iterator over mnemonics `[index, max]`, both inclusive.
143    pub fn new(function: &'a Function,index: usize, max: usize) -> MnemonicIterator<'a> {
144        MnemonicIterator{
145            function: function,
146            index: index,
147            max: max,
148        }
149    }
150}
151
152impl<'a> Iterator for MnemonicIterator<'a> {
153    type Item = (MnemonicIndex,&'a Mnemonic);
154
155    fn next(&mut self) -> Option<(MnemonicIndex,&'a Mnemonic)> {
156        if self.index <= self.max {
157            let idx = MnemonicIndex::new(self.index);
158            let mne = self.function.mnemonic(idx);
159
160            self.index += 1;
161            Some((idx,mne))
162        } else {
163            None
164        }
165    }
166}
167
168impl<'a> ExactSizeIterator for MnemonicIterator<'a> {
169    fn len(&self) -> usize {
170        self.max - self.index + 1
171    }
172}
173
174impl<'a> DoubleEndedIterator for MnemonicIterator<'a> {
175    fn next_back(&mut self) -> Option<(MnemonicIndex,&'a Mnemonic)> {
176        if self.index <= self.max {
177            let idx = MnemonicIndex::new(self.max);
178            let mne = self.function.mnemonic(idx);
179
180            if self.max == self.index {
181                self.index = self.max + 1;
182            } else {
183                self.max -= 1;
184            }
185            Some((idx,mne))
186        } else {
187            None
188        }
189    }
190}
191
192#[cfg(test)]
193mod tests {
194    use super::*;
195    use ron_uuid::UUID;
196
197    /*
198     * (B0)
199     * 0:  Mix   ; mov i x
200     * 3:  J9    ; B1
201     *
202     * (B1)
203     * 9:  Mis   ; mov i s
204     * 12: R     ; ret
205     */
206    #[test]
207    fn mnemonic_iter() {
208        use {Region, TestArch};
209
210        let _ = simple_logger::init();
211        let data = b"MixJ9xxxxMisR".to_vec();
212        let reg = Region::from_buf("", 16, data, 0, None);
213        let func = Function::new::<TestArch>((), 0, &reg, UUID::now()).unwrap();
214
215        let (bb0_idx, bb0) = func.basic_blocks().next().unwrap();
216        let (bb1_idx, bb1) = func.basic_blocks().skip(1).next().unwrap();
217
218        assert_eq!(bb0.mnemonics, MnemonicIndex::new(0)..MnemonicIndex::new(2));
219        assert_eq!(bb1.mnemonics, MnemonicIndex::new(2)..MnemonicIndex::new(4));
220        assert_eq!(func.mnemonics(bb0_idx).count(), 2);
221        assert_eq!(func.mnemonics(bb0_idx).len(), 2);
222        assert_eq!(func.mnemonics(bb1_idx).count(), 2);
223        assert_eq!(func.mnemonics(bb1_idx).len(), 2);
224        assert_eq!(func.mnemonics(bb0_idx).rev().count(), 2);
225        assert_eq!(func.mnemonics(bb1_idx).rev().count(), 2);
226    }
227}