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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#![allow(non_snake_case)]

use memmap::{Mmap, MmapOptions};
use ouroboros::self_referencing;
use scroll::Pread;
use std::fs::File;
use std::marker::PhantomData;
use std::path::Path;

#[macro_use]
extern crate bitflags;

mod error;
pub use error::Error;

mod parse;
pub use parse::*;

pub type Result<T> = std::result::Result<T, error::Error>;

#[self_referencing(no_doc)]
pub struct VTIL<T: 'static> {
    source: Box<T>,
    #[borrows(source)]
    pub(crate) inner: VTILInner<'this>,
    phantom: PhantomData<T>,
}

impl<T> VTIL<T> {
    pub fn header(&self) -> &Header {
        self.inner.header()
    }

    pub fn vip(&self) -> &Vip {
        self.inner.vip()
    }

    pub fn routine_convention(&self) -> &RoutineConvention {
        self.inner.routine_convention()
    }

    pub fn subroutine_convention(&self) -> &SubroutineConvention {
        self.inner.subroutine_convention()
    }

    pub fn spec_subroutine_conventions(&self) -> &Vec<SubroutineConvention> {
        self.inner.spec_subroutine_conventions()
    }

    pub fn explored_blocks(&self) -> &Vec<BasicBlock> {
        self.inner.explored_blocks()
    }
}

/// Reader for VTIL containers
pub struct VTILReader;

impl VTILReader {
    /// Tries to load VTIL from the given path
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<VTIL<Mmap>> {
        let source = Box::new(unsafe { MmapOptions::new().map(&File::open(path.as_ref())?)? });
        VTILTryBuilder {
            source,
            inner_builder: |source| source.pread_with::<VTILInner>(0, scroll::LE),
            phantom: PhantomData,
        }
        .try_build()
    }

    /// Loads VTIL from a `Vec<u8>`
    pub fn from_vec<B: AsRef<[u8]>>(source: B) -> Result<VTIL<B>> {
        VTILTryBuilder {
            source: Box::new(source),
            inner_builder: |source| source.as_ref().pread_with::<VTILInner>(0, scroll::LE),
            phantom: PhantomData,
        }
        .try_build()
    }
}