@@ -26,12 +26,12 @@ use std::slice;
2626
2727use crate :: architecture:: Architecture ;
2828use crate :: binary_view:: { BinaryView , BinaryViewBase , BinaryViewExt , Result } ;
29+ use crate :: metadata:: Metadata ;
2930use crate :: platform:: Platform ;
30- use crate :: settings:: Settings ;
31- use crate :: Endianness ;
32-
3331use crate :: rc:: * ;
32+ use crate :: settings:: Settings ;
3433use 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