Skip to content

Commit 57d04f2

Browse files
committed
Add platform recognizer to Rust API
1 parent e45f0e0 commit 57d04f2

File tree

1 file changed

+65
-3
lines changed

1 file changed

+65
-3
lines changed

rust/src/custom_binary_view.rs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ use std::slice;
2626

2727
use crate::architecture::Architecture;
2828
use crate::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt, Result};
29+
use crate::metadata::Metadata;
2930
use crate::platform::Platform;
30-
use crate::settings::Settings;
31-
use crate::Endianness;
32-
3331
use crate::rc::*;
32+
use crate::settings::Settings;
3433
use crate::string::*;
34+
use crate::Endianness;
3535

3636
/// Registers a custom `BinaryViewType` with the core.
3737
///
@@ -238,6 +238,68 @@ pub trait BinaryViewTypeExt: BinaryViewTypeBase {
238238
}
239239
}
240240

241+
/// Expanded identification of [`Platform`] for [`BinaryViewType`]'s. Supersedes [`BinaryViewTypeExt::register_arch`]
242+
/// and [`BinaryViewTypeExt::register_platform`], as these have certain edge cases (overloaded elf families, for example)
243+
/// that can't be represented.
244+
///
245+
/// The callback returns a [`Platform`] object or `None` (failure), and most recently added callbacks are called first
246+
/// to allow plugins to override any default behaviors. When a callback returns a platform, architecture will be
247+
/// derived from the identified platform.
248+
///
249+
/// The [`BinaryView`] is the *parent* view (usually 'Raw') that the [`BinaryView`] is being created for. This
250+
/// means that generally speaking the callbacks need to be aware of the underlying file format, however the
251+
/// [`BinaryView`] implementation may have created datavars in the 'Raw' view by the time the callback is invoked.
252+
/// Behavior regarding when this callback is invoked and what has been made available in the [`BinaryView`] passed as an
253+
/// argument to the callback is up to the discretion of the [`BinaryView`] implementation.
254+
///
255+
/// The `id` ind `endian` arguments are used as a filter to determine which registered [`Platform`] recognizer callbacks
256+
/// are invoked.
257+
///
258+
/// Support for this API tentatively requires explicit support in the [`BinaryView`] implementation.
259+
fn register_platform_recognizer<R>(&self, id: u32, endian: Endianness, recognizer: R)
260+
where
261+
R: 'static + Fn(&BinaryView, &Metadata) -> Option<Platform> + Send + Sync,
262+
{
263+
#[repr(C)]
264+
struct PlatformRecognizerHandlerContext<R>
265+
where
266+
R: 'static + Fn(&BinaryView, &Metadata) -> Option<Platform> + Send + Sync,
267+
{
268+
recognizer: R,
269+
}
270+
271+
extern "C" fn cb_recognize_low_level_il<R>(
272+
ctxt: *mut c_void,
273+
bv: *mut BNBinaryView,
274+
metadata: *mut BNMetadata,
275+
) -> *mut BNPlatform
276+
where
277+
R: 'static + Fn(&BinaryView, &Metadata) -> Option<Platform> + Send + Sync,
278+
{
279+
let context = unsafe { &*(ctxt as *mut PlatformRecognizerHandlerContext<R>) };
280+
let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
281+
let metadata = unsafe { Metadata::from_raw(metadata).to_owned() };
282+
match (context.recognizer)(&bv, &metadata) {
283+
Some(plat) => plat.handle,
284+
None => std::ptr::null_mut(),
285+
}
286+
}
287+
288+
let recognizer = PlatformRecognizerHandlerContext { recognizer };
289+
// TODO: Currently we leak `recognizer`.
290+
let raw = Box::into_raw(Box::new(recognizer));
291+
292+
unsafe {
293+
BNRegisterPlatformRecognizerForViewType(
294+
self.as_ref().handle,
295+
id as u64,
296+
endian,
297+
Some(cb_recognize_low_level_il::<R>),
298+
raw as *mut c_void,
299+
)
300+
}
301+
}
302+
241303
fn open(&self, data: &BinaryView) -> Result<Ref<BinaryView>> {
242304
let handle = unsafe { BNCreateBinaryViewOfType(self.as_ref().handle, data.handle) };
243305

0 commit comments

Comments
 (0)