binaryninja/
function_recognizer.rs

1use crate::low_level_il::function::LowLevelILFunction;
2use crate::low_level_il::LowLevelILRegularFunction;
3use crate::medium_level_il::MediumLevelILFunction;
4use crate::{architecture::CoreArchitecture, binary_view::BinaryView, function::Function};
5use binaryninjacore_sys::*;
6use std::os::raw::c_void;
7
8pub trait FunctionRecognizer {
9    fn recognize_low_level_il(
10        &self,
11        _bv: &BinaryView,
12        _func: &Function,
13        _llil: &LowLevelILRegularFunction,
14    ) -> bool {
15        false
16    }
17
18    fn recognize_medium_level_il(
19        &self,
20        _bv: &BinaryView,
21        _func: &Function,
22        _mlil: &MediumLevelILFunction,
23    ) -> bool {
24        false
25    }
26}
27
28fn create_function_recognizer_registration<R>(recognizer: R) -> BNFunctionRecognizer
29where
30    R: 'static + FunctionRecognizer + Send + Sync + Sized,
31{
32    #[repr(C)]
33    struct FunctionRecognizerHandlerContext<R>
34    where
35        R: 'static + FunctionRecognizer + Send + Sync,
36    {
37        recognizer: R,
38    }
39
40    extern "C" fn cb_recognize_low_level_il<R>(
41        ctxt: *mut c_void,
42        bv: *mut BNBinaryView,
43        func: *mut BNFunction,
44        llil: *mut BNLowLevelILFunction,
45    ) -> bool
46    where
47        R: 'static + FunctionRecognizer + Send + Sync,
48    {
49        let context = unsafe { &*(ctxt as *mut FunctionRecognizerHandlerContext<R>) };
50        let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
51        let func = unsafe { Function::from_raw(func).to_owned() };
52        let llil = unsafe { LowLevelILFunction::from_raw(llil).to_owned() };
53        let _span = ffi_span!("FunctionRecognizer::recognize_low_level_il", bv);
54        context.recognizer.recognize_low_level_il(&bv, &func, &llil)
55    }
56
57    extern "C" fn cb_recognize_medium_level_il<R>(
58        ctxt: *mut c_void,
59        bv: *mut BNBinaryView,
60        func: *mut BNFunction,
61        mlil: *mut BNMediumLevelILFunction,
62    ) -> bool
63    where
64        R: 'static + FunctionRecognizer + Send + Sync,
65    {
66        let context = unsafe { &*(ctxt as *mut FunctionRecognizerHandlerContext<R>) };
67        let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
68        let func = unsafe { Function::from_raw(func).to_owned() };
69        let mlil = unsafe { MediumLevelILFunction::from_raw(mlil).to_owned() };
70        let _span = ffi_span!("FunctionRecognizer::recognize_medium_level_il", bv);
71        context
72            .recognizer
73            .recognize_medium_level_il(&bv, &func, &mlil)
74    }
75
76    let recognizer = FunctionRecognizerHandlerContext { recognizer };
77    // TODO: Currently we leak `recognizer`.
78    let raw = Box::into_raw(Box::new(recognizer));
79    BNFunctionRecognizer {
80        context: raw as *mut _,
81        recognizeLowLevelIL: Some(cb_recognize_low_level_il::<R>),
82        recognizeMediumLevelIL: Some(cb_recognize_medium_level_il::<R>),
83    }
84}
85
86pub fn register_global_function_recognizer<R>(recognizer: R)
87where
88    R: 'static + FunctionRecognizer + Send + Sync + Sized,
89{
90    let mut recognizer = create_function_recognizer_registration::<R>(recognizer);
91    unsafe {
92        BNRegisterGlobalFunctionRecognizer(&mut recognizer);
93    }
94}
95
96pub(crate) fn register_arch_function_recognizer<R>(arch: &CoreArchitecture, recognizer: R)
97where
98    R: 'static + FunctionRecognizer + Send + Sync + Sized,
99{
100    let mut recognizer = create_function_recognizer_registration::<R>(recognizer);
101    unsafe {
102        BNRegisterArchitectureFunctionRecognizer(arch.handle, &mut recognizer);
103    }
104}