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, ®, 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}