summaryrefslogtreecommitdiff
path: root/plugins/warp/src/plugin/load.rs
blob: 03356444c51b61bb1aeee070f1af6d5047dca1e7 (plain)
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
use crate::matcher::{Matcher, PlatformID, PLAT_MATCHER_CACHE};
use binaryninja::binaryview::{BinaryView, BinaryViewExt};
use binaryninja::command::Command;
pub struct LoadSignatureFile;

impl Command for LoadSignatureFile {
    fn action(&self, view: &BinaryView) {
        let Some(platform) = view.default_platform() else {
            log::error!("Default platform must be set to load signature!");
            return;
        };

        let Some(file) =
            binaryninja::interaction::get_open_filename_input("Load Signature File", "*.sbin")
        else {
            return;
        };

        let Ok(data) = std::fs::read(&file) else {
            log::error!("Could not read signature file: {:?}", file);
            return;
        };

        let Some(data) = warp::signature::Data::from_bytes(&data) else {
            log::error!("Could not get data from signature file: {:?}", file);
            return;
        };

        let new_matcher = Matcher::from_data(data);
        log::info!(
            "Loading signature file with {} functions and {} types...",
            new_matcher.functions.len(),
            new_matcher.types.len()
        );
        let platform_id = PlatformID::from(platform.as_ref());
        let matcher_cache = PLAT_MATCHER_CACHE.get_or_init(Default::default);
        match matcher_cache.get_mut(&platform_id) {
            Some(mut matcher) => matcher.extend_with_matcher(new_matcher),
            None => {
                // We still must uphold `from_platform` in case we are running this before the matcher workflow
                // is kicked off. Other-wise we only will have the `new_matcher` data.
                let mut matcher = Matcher::from_platform(platform);
                matcher.extend_with_matcher(new_matcher);
                matcher_cache.insert(platform_id, matcher);
            }
        }
    }

    fn valid(&self, _view: &BinaryView) -> bool {
        true
    }
}