11use core:: ffi;
2+ use core:: pin:: Pin ;
23use core:: ptr;
34use std:: ffi:: CStr ;
45
@@ -40,7 +41,7 @@ macro_rules! trait_handler {
4041 /// Used to describe which call should be triggered by BinaryNinja.
4142 /// By default all calls are disabled.
4243 ///
43- /// Used by [CustomDataNotification::register]
44+ /// Used by [CustomDataNotification::register] and [register_data_notification].
4445 #[ derive( Default ) ]
4546 pub struct DataNotificationTriggers {
4647 $( $fun_name: bool , ) *
@@ -62,12 +63,16 @@ macro_rules! trait_handler {
6263 }
6364 ) *
6465
66+ /// Register the data notification functions.
67+ ///
68+ /// If the type don't implement Unpin, use the function
69+ /// [register_data_notification] with the pinned value.
6570 fn register<' a>(
66- self ,
71+ & ' a mut self ,
6772 view: & BinaryView ,
6873 triggers: DataNotificationTriggers ,
69- ) -> DataNotificationHandle <' a, Self > where Self : ' a + Sized {
70- register_data_notification( view, self , triggers)
74+ ) -> DataNotificationHandle <' a, Self > where Self : ' a + Sized + Unpin {
75+ register_data_notification( view, Pin :: new ( self ) , triggers)
7176 }
7277 }
7378 $(
@@ -79,15 +84,14 @@ macro_rules! trait_handler {
7984 handle. $fun_name( $( $value_calculated) ,* )
8085 }
8186 ) *
82- fn register_data_notification<' a, H : CustomDataNotification + ' a >(
87+ pub fn register_data_notification<' a, H : ' a + CustomDataNotification >(
8388 view: & BinaryView ,
84- notify: H ,
89+ notify: Pin < & ' a H > ,
8590 triggers: DataNotificationTriggers ,
8691 ) -> DataNotificationHandle <' a, H > {
87- // SAFETY: this leak is undone on drop
88- let leak_notify = Box :: leak( Box :: new( notify) ) ;
92+ let notify = unsafe { Pin :: into_inner_unchecked( notify) as * const H } ;
8993 let mut handle = BNBinaryDataNotification {
90- context: leak_notify as * mut _ as * mut ffi:: c_void,
94+ context: notify as * const ffi :: c_void as * mut ffi:: c_void,
9195 $( $ffi_param_name: triggers. $fun_name. then_some( $fun_name:: <H >) ) ,*
9296 } ;
9397 unsafe { BNRegisterDataNotification ( view. handle, & mut handle) } ;
@@ -140,7 +144,7 @@ macro_rules! trait_handler {
140144 ) *
141145
142146 pub fn register(
143- self ,
147+ & ' a self ,
144148 view: & BinaryView ,
145149 ) -> DataNotificationHandle <' a, Self > {
146150 let mut triggers = DataNotificationTriggers :: default ( ) ;
@@ -149,7 +153,7 @@ macro_rules! trait_handler {
149153 triggers = triggers. $fun_name( ) ;
150154 }
151155 ) *
152- register_data_notification( view, self , triggers)
156+ register_data_notification( view, Pin :: new ( self ) , triggers)
153157 }
154158 }
155159
@@ -402,36 +406,14 @@ trait_handler! {
402406 ) ,
403407}
404408
405- pub struct DataNotificationHandle < ' a , T : CustomDataNotification >
406- where
407- T : ' a ,
408- {
409+ pub struct DataNotificationHandle < ' a , T > {
409410 bv : Ref < BinaryView > ,
410411 handle : BNBinaryDataNotification ,
411412 _life : std:: marker:: PhantomData < & ' a T > ,
412413}
413414
414- impl < T : CustomDataNotification > DataNotificationHandle < ' _ , T > {
415- unsafe fn unregister_bv ( & mut self ) {
416- BNUnregisterDataNotification ( self . bv . handle , & mut self . handle )
417- }
418-
419- unsafe fn extract_context ( & mut self ) -> Box < T > {
420- Box :: from_raw ( self . handle . context as * mut T )
421- }
422-
423- pub fn unregister ( self ) -> T {
424- // NOTE don't drop the ctxt, return it
425- let mut slf = core:: mem:: ManuallyDrop :: new ( self ) ;
426- unsafe { slf. unregister_bv ( ) } ;
427- unsafe { * slf. extract_context ( ) }
428- }
429- }
430-
431- impl < T : CustomDataNotification > Drop for DataNotificationHandle < ' _ , T > {
415+ impl < ' a , T > Drop for DataNotificationHandle < ' a , T > {
432416 fn drop ( & mut self ) {
433- unsafe { self . unregister_bv ( ) } ;
434- // drop context, avoid memory leak
435- let _ctxt = unsafe { self . extract_context ( ) } ;
417+ unsafe { BNUnregisterDataNotification ( self . bv . handle , & mut self . handle ) }
436418 }
437419}
0 commit comments