p8n_types/
architecture.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::borrow::Cow;
20
21use smallvec::SmallVec;
22use ron_uuid::UUID;
23
24use {
25    Region,
26    Result,
27    Value,
28    Variable,
29    Statement,
30    Operation,
31    FlowOperation,
32    MemoryOperation,
33    Guard,
34    Str,
35    Names,
36    Segments,
37    Segment,
38    Name,
39    Endianess,
40    Strings,
41};
42
43/// CPU architecture and instruction set.
44pub trait Architecture: Clone {
45    /// This type can describes the CPU state. For x86 this would be the mode, for ARM whenever
46    /// Thumb is active.
47    type Configuration: Clone + Send;
48
49    /// Given a memory image and a configuration the functions extracts a set of entry points.
50    /// # Return
51    /// Tuples of entry point name, offset form the start of the region and optional comment.
52    fn prepare(&Region, &Self::Configuration) -> Result<Cow<'static, [(&'static str, u64, &'static str)]>>;
53
54    /// Start to disassemble a single Opcode inside a given region at a given address.
55    fn decode(&Region, u64, &Self::Configuration, names: &mut Names,
56              segments: &mut Segments, strings: &mut Strings,
57              matches: &mut Vec<Match>) -> Result<()>;
58}
59
60/// Result of a single disassembly operation.
61#[derive(Debug,Clone)]
62pub struct Match {
63    /// Recognized address range
64    pub area: Range<u64>,
65    /// Matched mnemonic.
66    pub opcode: Str,
67    /// Opcode arguments.
68    pub operands: SmallVec<[Value; 3]>,
69    //pub format_string: SmallVec<[MnemonicFormatToken; 5]>,
70    /// IL statements modeling the semantics.
71    pub instructions: Vec<Statement>,
72
73    /// Jumps/branches originating from the recovered mnemonics
74    pub jumps: SmallVec<[(u64, Value, Guard); 2]>,
75}
76
77/// ISA used for testing.
78/// Single digits are interpreted as 32 bit constants, lower case letters as 32 bit registers or 1
79/// bit flags depending on the context. First argument is the result. Upper case letters are
80/// opcodes.
81///
82/// # Instructions
83///
84/// 'A' <x> <y> <z>: <x> := <y> + <z>
85/// 'X' <x> <y> <z>: <x> := <y> * <z>
86/// 'U' <x> <y> <z>: <x> := <y> - <z>
87/// 'M' <x> <y>: <x> := <y>
88/// 'C' <x> <y> <z>: <x> := <y> <= <z> ? 1 : 0 # <x> is a 1 bit flag
89/// 'E' <x> <y> <z>: <x> := <y> == <z> ? 1 : 0 # <x> is a 1 bit flag
90/// 'B' <x> <y>: branch to <y> if flag <y> is 1, fall-thru otherwise
91/// 'J' <x>: jump to
92/// 'G' <x>: call to <x>
93/// 'F': call to random uuid
94/// 'H' <x>: call to stub x
95/// 'R': return
96/// 'S' <x> <y>: *x := y
97/// 'L' <x> <y>: x := *y
98#[derive(Debug,Clone)]
99pub struct TestArch;
100
101impl TestArch {
102    fn read_value(reg: &Region, entry: &mut u64, len: usize, names: &mut Names) -> Result<Value> {
103        match reg.read_integer(*entry,Endianess::Little,1).map(|x| x as u8) {
104            Ok(b) => match b {
105                b'a'...b'z' => {
106                    let nam = names.insert(&Name::new(format!("{}",char::from(b)).into(),None));
107
108                    *entry += 1;
109                    Value::var(nam,len)
110                }
111                b'0'...b'9' => {
112                    Value::val(Self::read_address(reg,entry)?,32)
113                }
114                _ => Err(format!("'{}' is nor a variable name neither a constant",b).into())
115            }
116            _ => Err(format!("premature end while decoding rvalue at {}",*entry).into())
117        }
118    }
119
120    fn read_variable(reg: &Region, entry: &mut u64, len: usize, names: &mut Names) -> Result<Variable> {
121        match reg.read_integer(*entry,Endianess::Little,1).map(|x| x as u8) {
122            Ok(b) => match b {
123                b'a'...b'z' => {
124                    let nam = names.insert(&Name::new(format!("{}",char::from(b)).into(),None));
125
126                    *entry += 1;
127                    Variable::new(nam,len)
128                }
129                _ => Err(format!("'{}' is not a variable name",b).into())
130            }
131            _ => Err(format!("Premature end while decoding lvalue at {}",*entry).into())
132        }
133    }
134
135    fn read_address(reg: &Region, entry: &mut u64) -> Result<u64> {
136        match reg.read_integer(*entry,Endianess::Little,1).map(|x| x as u8) {
137            Ok(b@b'0'...b'9') => {
138                let value = (b - b'0') as u64;
139
140                *entry += 1;
141                match Self::read_address(reg,entry) {
142                    Ok(x) => Ok(value * 10 + x),
143                    Err(_) => Ok(value)
144                }
145            }
146            Ok(b) => Err(format!("'{}' is not a number",b).into()),
147            _ => Err(format!("Premature end while decoding address at {}",*entry).into())
148        }
149    }
150}
151
152impl Architecture for TestArch {
153    type Configuration = ();
154
155    fn prepare(_: &Region, _: &()) -> Result<Cow<'static, [(&'static str, u64, &'static str)]>> {
156        Ok(Cow::default())
157    }
158
159    fn decode(reg: &Region, mut entry: u64, _: &(), names: &mut Names,
160              segments: &mut Segments, strings: &mut Strings,
161              matches: &mut Vec<Match>) -> Result<()>
162    {
163        let start = entry;
164        let opcode = reg.read_integer(entry,Endianess::Little,1);
165        entry += 1;
166
167        match opcode.map(|x| x as u8) {
168            Ok(b'M') => {
169                let var = Self::read_variable(reg, &mut entry, 32, names)?;
170                let val = Self::read_value(reg, &mut entry, 32, names)?;
171                let instr = Statement::Expression{
172                    result: var.clone(),
173                    op: Operation::Move(val.clone())
174                };
175                let m = Match{
176                    area: start..entry,
177                    opcode: "mov".into(),
178                    operands: SmallVec::from_vec(vec![var.into(), val]),
179                    instructions: vec![instr],
180                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
181                };
182
183                matches.push(m);
184                Ok(())
185            }
186            Ok(b'G') => {
187                let addr = Self::read_variable(reg, &mut entry, 32, names)?;
188                let instr = Statement::Flow{
189                    op: FlowOperation::IndirectCall{ target: addr },
190                };
191                let m = Match{
192                    area: start..entry,
193                    opcode: "call".into(),
194                    operands: SmallVec::from_vec(vec![addr.into()]),
195                    instructions: vec![instr],
196                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
197                };
198
199                matches.push(m);
200                Ok(())
201            }
202            Ok(b'F') => {
203                let instr = Statement::Flow{
204                    op: FlowOperation::Call{ function: UUID::now() },
205                };
206                let m = Match{
207                    area: start..entry,
208                    opcode: "call".into(),
209                    operands: SmallVec::default(),
210                    instructions: vec![instr],
211                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
212                };
213
214                matches.push(m);
215                Ok(())
216            }
217            Ok(b'H') => {
218                let s = match reg.read_integer(entry,Endianess::Little,1) {
219                    Ok(b) => {
220                        entry += 1;
221                        strings.insert(&format!("{}", char::from(b as u8)).into())
222                    }
223                    _ => {
224                        return Err(format!("premature end while decoding stub name {}",entry).into());
225                    }
226                };
227                let instr = Statement::Flow{
228                    op: FlowOperation::ExternalCall{ external: s.into() },
229                };
230                let m = Match{
231                    area: start..entry,
232                    opcode: "call".into(),
233                    operands: SmallVec::default(),
234                    instructions: vec![instr],
235                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
236                };
237
238                matches.push(m);
239                Ok(())
240            }
241            Ok(b'A') => {
242                let var = Self::read_variable(reg, &mut entry, 32, names)?;
243                let val1 = Self::read_value(reg, &mut entry, 32, names)?;
244                let val2 = Self::read_value(reg, &mut entry, 32, names)?;
245                let instr = Statement::Expression{
246                    result: var,
247                    op: Operation::Add(val1.clone(),val2.clone())
248                };
249                let m = Match{
250                    area: start..entry,
251                    opcode: "add".into(),
252                    operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
253                    instructions: vec![instr],
254                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
255                };
256
257                matches.push(m);
258                Ok(())
259            }
260            Ok(b'U') => {
261                let var = Self::read_variable(reg, &mut entry, 32, names)?;
262                let val1 = Self::read_value(reg, &mut entry, 32, names)?;
263                let val2 = Self::read_value(reg, &mut entry, 32, names)?;
264                let instr = Statement::Expression{
265                    result: var,
266                    op: Operation::Subtract(val1.clone(),val2.clone())
267                };
268                let m = Match{
269                    area: start..entry,
270                    opcode: "sub".into(),
271                    operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
272                    instructions: vec![instr],
273                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
274                };
275
276                matches.push(m);
277                Ok(())
278            }
279            Ok(b'X') => {
280                let var = Self::read_variable(reg, &mut entry, 32, names)?;
281                let val1 = Self::read_value(reg, &mut entry, 32, names)?;
282                let val2 = Self::read_value(reg, &mut entry, 32, names)?;
283                let instr = Statement::Expression{
284                    result: var,
285                    op: Operation::Multiply(val1,val2)
286                };
287                let m = Match{
288                    area: start..entry,
289                    opcode: "mul".into(),
290                    operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
291                    instructions: vec![instr],
292                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
293                };
294
295                matches.push(m);
296                Ok(())
297            }
298            Ok(b'C') => {
299                let var = Self::read_variable(reg, &mut entry, 1, names)?;
300                let val1 = Self::read_value(reg, &mut entry, 32, names)?;
301                let val2 = Self::read_value(reg, &mut entry, 32, names)?;
302                let instr = Statement::Expression{
303                    result: var,
304                    op: Operation::LessOrEqualUnsigned(val1,val2)
305                };
306                let m = Match{
307                    area: start..entry,
308                    opcode: "leq".into(),
309                    operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
310                    instructions: vec![instr],
311                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
312                };
313
314                matches.push(m);
315                Ok(())
316            }
317            Ok(b'E') => {
318                let var = Self::read_variable(reg, &mut entry, 1, names)?;
319                let val1 = Self::read_value(reg, &mut entry, 32, names)?;
320                let val2 = Self::read_value(reg, &mut entry, 32, names)?;
321                let instr = Statement::Expression{
322                    result: var,
323                    op: Operation::Equal(val1,val2)
324                };
325                let m = Match{
326                    area: start..entry,
327                    opcode: "eq".into(),
328                    operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
329                    instructions: vec![instr],
330                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
331                };
332
333                matches.push(m);
334                Ok(())
335            }
336            Ok(b'B') => {
337                let bit = Self::read_variable(reg, &mut entry, 1, names)?;
338                let brtgt = Self::read_address(reg, &mut entry)?;
339                let guard = Guard::Predicate{ flag: bit, expected: true };
340                let nguard = Guard::Predicate{ flag: bit, expected: false };
341                let m = Match{
342                    area: start..entry,
343                    opcode: "br".into(),
344                    operands: SmallVec::from_vec(vec![Value::Variable(bit.clone()),Value::val(brtgt, 32)?]),
345                    instructions: vec![],
346                    jumps: SmallVec::from_vec(vec![
347                        (start,Value::val(entry, 32)?,nguard),
348                        (start,Value::val(brtgt, 32)?,guard)
349                    ]),
350                };
351
352                matches.push(m);
353                Ok(())
354            }
355            Ok(b'J') => {
356                let jtgt = Self::read_value(reg, &mut entry, 32, names)?;
357                let m = Match{
358                    area: start..entry,
359                    opcode: "jmp".into(),
360                    operands: SmallVec::from_vec(vec![jtgt]),
361                    instructions: vec![],
362                    jumps: SmallVec::from_vec(vec![(start,jtgt,Guard::True)]),
363                };
364
365                matches.push(m);
366                Ok(())
367            }
368            Ok(b'R') => {
369                let instr = Statement::Flow{
370                    op: FlowOperation::Return
371                };
372                let m = Match{
373                    area: start..entry,
374                    opcode: "ret".into(),
375                    operands: SmallVec::default(),
376                    instructions: vec![instr],
377                    jumps: SmallVec::default(),
378                };
379
380                matches.push(m);
381                Ok(())
382            }
383            Ok(b'S') => {
384                let addr = Self::read_value(reg, &mut entry, 32, names)?;
385                let val = Self::read_value(reg, &mut entry, 32, names)?;
386                let seg = Segment{ name: segments.insert(&Name::new("ram".into(),None)) };
387                let instr = Statement::Memory{
388                    result: seg,
389                    op: MemoryOperation::Store{
390                        segment: seg,
391                        endianess: Endianess::Little,
392                        bytes: 4,
393                        address: addr,
394                        value: val,
395                    }
396                };
397                let m = Match{
398                    area: start..entry,
399                    opcode: "store".into(),
400                    operands: SmallVec::from_vec(vec![addr.clone().into(),val.clone()]),
401                    instructions: vec![instr],
402                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
403                };
404
405                matches.push(m);
406                Ok(())
407            }
408            Ok(b'L') => {
409                let val = Self::read_variable(reg, &mut entry, 32, names)?;
410                let addr = Self::read_value(reg, &mut entry, 32, names)?;
411                let seg = segments.insert(&Name::new("ram".into(),None));
412                let instr = Statement::Expression{
413                    result: val,
414                    op: Operation::Load(Segment{ name: seg },Endianess::Little,4,addr)
415                };
416                let m = Match{
417                    area: start..entry,
418                    opcode: "load".into(),
419                    operands: SmallVec::from_vec(vec![val.clone().into(),addr.clone()]),
420                    instructions: vec![instr],
421                    jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
422                };
423
424                matches.push(m);
425                Ok(())
426            }
427            Ok(o) => {
428                Err(format!("Unknown opcode '{}' at {}",o,start).into())
429            }
430            _ => {
431                Err(format!("Premature end while decoding opcode {}",start).into())
432            }
433        }
434    }
435}
436
437#[cfg(test)]
438mod tests {
439    use super::*;
440    use {Function, Region};
441
442    #[test]
443    fn test_arch() {
444        let reg = Region::from_buf("",16,b"Mi1MiiAiiiAi1iAii1Ai11CiiiCi1iCii1Ci11Bi0RSiiS1iS11LiiLi1".to_vec(),0,None);
445        let _ = Function::new::<TestArch>((), 0, &reg, UUID::now()).unwrap();
446    }
447}