1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use std::collections::HashSet;
use std::collections::HashMap;
use bb_disassembler::BBDisassembler;
use basic_block::BasicBlock;

#[derive(Debug, Eq, PartialEq)]
pub struct Disassembly{
    pub offset: u64,
    pub data: Vec<u8>,
    pub bbs: HashMap<u64, BasicBlock>,
}

pub struct RecursiveDisassembler<T: BBDisassembler> {
    pub offset: u64,
    pub data: Vec<u8>,
    pub roots: HashSet<u64>,
    pub bbs: HashMap<u64, BasicBlock>,
    dis: T,
    unprocessed_roots: HashSet<u64>,
}

impl<T: BBDisassembler> RecursiveDisassembler<T> {
    pub fn new(data: Vec<u8>, offset: u64, dis: T) -> Self {
        let unprocessed_roots = HashSet::new();
        let roots = HashSet::new();
        let bbs = HashMap::new();
        return RecursiveDisassembler { offset, data, dis, roots, unprocessed_roots, bbs };
    }

    pub fn add_root(&mut self, addr: u64) {
        if !self.roots.contains(&addr) {
            self.unprocessed_roots.insert(addr);
        }
    }

    pub fn disassemble(&mut self) {
        while let Some(&root) = self.unprocessed_roots.iter().next() {
            self.unprocessed_roots.remove(&root);
            if !self.in_range(root) { continue; }
            self.roots.insert(root);
            let bb = self.dis.get_basic_block(root, self.offset, &self.data);

            for addr in bb.successors() {
                self.add_root(addr);
            }
            self.bbs.insert(root, bb);
        }
    }

    fn in_range(&self, addr: u64) -> bool {
        return (self.offset <= addr) && (self.offset + self.data.len() as u64 > addr);
    }

    pub fn into_disassembly(self) -> Disassembly{
        let RecursiveDisassembler{ offset, data, bbs, ..} = self;
        return Disassembly{offset, data, bbs}
    }
}