From 270adb49ed0f52b8c76bdd3ee2f18f773cdecae5 Mon Sep 17 00:00:00 2001 From: rbran Date: Tue, 1 Apr 2025 13:20:10 +0000 Subject: [PATCH 1/4] Implement DataNotification for rust --- rust/src/data_notification.rs | 915 ++++++++++++++++++++++++++++++++ rust/src/lib.rs | 1 + rust/src/section.rs | 2 +- rust/tests/data_notification.rs | 131 +++++ 4 files changed, 1048 insertions(+), 1 deletion(-) create mode 100644 rust/src/data_notification.rs create mode 100644 rust/tests/data_notification.rs diff --git a/rust/src/data_notification.rs b/rust/src/data_notification.rs new file mode 100644 index 000000000..049b2d40c --- /dev/null +++ b/rust/src/data_notification.rs @@ -0,0 +1,915 @@ +use core::ffi; +use core::ptr; +use std::ffi::CStr; + +use binaryninjacore_sys::{ + BNBinaryDataNotification, BNBinaryView, BNComponent, BNDataVariable, BNExternalLibrary, + BNExternalLocation, BNFunction, BNQualifiedName, BNRegisterDataNotification, BNSection, + BNSegment, BNStringType, BNSymbol, BNTagReference, BNTagType, BNType, BNTypeArchive, + BNUndoEntry, BNUnregisterDataNotification, +}; + +use crate::binary_view::BinaryView; +use crate::component::Component; +use crate::database::undo::UndoEntry; +use crate::disassembly::StringType; +use crate::external_library::{ExternalLibrary, ExternalLocation}; +use crate::function::Function; +use crate::rc::Ref; +use crate::section::Section; +use crate::segment::Segment; +use crate::symbol::Symbol; +use crate::tags::{TagReference, TagType}; +use crate::type_archive::TypeArchive; +use crate::types::{QualifiedName, Type}; +use crate::variable::DataVariable; + +macro_rules! trait_handler { +( + $( + $type_name:ident => { + $trait_name:ident, + $dummy_impl_name:ident, + $impl_fun_name:ident, + $ffi_fun_name:ident, + $ffi_param_name:ident, + $fun_name:ident($($arg_name:ident : $raw_arg_type:ty : $arg_type:ty),* $(,)?) $(-> $ret_type:ty)?, + ($($value_calculated:expr),* $(,)?) + $(,)? + } $(,)? + )* +) => { + pub trait CustomDataNotification: Sync + Send { + $(type $type_name: $trait_name;)* + // TODO once this becomes stable add a default type impl + // https://github.com/rust-lang/rust/issues/29661 + //$(type $type_name: $trait_name = $dummy_impl_name;)* + + $( + #[inline] + fn $impl_fun_name(&mut self) -> Option<&mut Self::$type_name> { + None + } + )* + + fn register<'a>(self, view: &BinaryView) -> DataNotificationHandle<'a, Self> where Self: 'a + Sized { + register_data_notification(view, self) + } + } + $( + pub trait $trait_name { + fn $fun_name(&mut self, $($arg_name: $arg_type),*) $(-> $ret_type)*; + } + + pub struct $dummy_impl_name; + impl $trait_name for $dummy_impl_name { + #[allow(unused_variables)] + fn $fun_name(&mut self, $($arg_name: $arg_type),*) $(-> $ret_type)* { + $( + const RET_VALUE: $ret_type = 0; + RET_VALUE + )* + } + } + + unsafe extern "C" fn $ffi_fun_name( + ctxt: *mut ::std::os::raw::c_void, + $($arg_name: $raw_arg_type),* + ) $(-> $ret_type)* { + let handle: &mut H = &mut *(ctxt as *mut H); + let Some(callback) = handle.$impl_fun_name() else { + unreachable!(); + }; + callback.$fun_name($($value_calculated),*) + } + )* + pub fn register_data_notification<'a, H: CustomDataNotification + 'a>( + view: &BinaryView, + notify: H, + ) -> DataNotificationHandle<'a, H> { + // SAFETY: this leak is undone on drop + let leak_notify = Box::leak(Box::new(notify)); + let mut handle = BNBinaryDataNotification { + context: leak_notify as *mut _ as *mut ffi::c_void, + $( + $ffi_param_name: leak_notify + .$impl_fun_name() + .is_some() + .then_some($ffi_fun_name::), + )* + }; + unsafe { BNRegisterDataNotification(view.handle, &mut handle) }; + DataNotificationHandle { + bv: view.to_owned(), + handle, + _life: std::marker::PhantomData, + } + } + + pub struct DataNotificationClosure<'a> { + $( + $fun_name: Option $ret_type)* + Sync + Send + 'a>>, + )* + } + + impl Default for DataNotificationClosure<'_> { + fn default() -> Self { + Self { $($fun_name: None,)* } + } + } + + impl<'a> DataNotificationClosure<'a> { + pub fn new() -> Self { + Default::default() + } + $( + pub fn $fun_name $ret_type)* + Sync + Send + 'a>(mut self, param: F) -> Self { + self.$fun_name = Some(Box::new(param)); + self + } + )* + + pub fn register(self, view: &BinaryView) -> DataNotificationHandle<'a, Self> { + register_data_notification(view, self) + } + } + + impl CustomDataNotification for DataNotificationClosure<'_> { + $( + type $type_name = Self; + fn $impl_fun_name(&mut self) -> Option<&mut Self::$type_name> { + self.$fun_name.is_some().then_some(self) + } + )* + } + + $( + impl $trait_name for DataNotificationClosure<'_> { + fn $fun_name(&mut self, $($arg_name: $arg_type),*) $(-> $ret_type)* { + let Some(handle) = self.$fun_name.as_mut() else { + unreachable!(); + }; + handle($($arg_name),*) + } + } + )* + + }; +} + +trait_handler!( +NotificationBarrier => { + NotificationBarrierHandler, + NotificationBarrierDummy, + notification_barrier_impl, + notification_barrier_ffi, + notificationBarrier, + notification_barrier(view: *mut BNBinaryView: &BinaryView) -> u64, + (&BinaryView::from_raw(view)), +} +DataWritten => { + DataWrittenHandler, + DataWrittenDummy, + data_written_impl, + data_written_ffi, + dataWritten, + data_written( + view: *mut BNBinaryView: &BinaryView, + offset: u64: u64, + len: usize: usize, + ), + (&BinaryView::from_raw(view), offset, len), +} +DataInserted => { + DataInsertedHandler, + DataInsertedDummy, + data_inserted_impl, + data_inserted_ffi, + dataInserted, + data_inserted( + view: *mut BNBinaryView: &BinaryView, + offset: u64: u64, + len: usize: usize, + ), + (&BinaryView::from_raw(view), offset, len), +} +DataRemoved => { + DataRemovedHandler, + DataRemovedDummy, + data_removed_impl, + data_removed_ffi, + dataRemoved, + data_removed( + view: *mut BNBinaryView: &BinaryView, + offset: u64: u64, + // TODO why the len is u64 here? Maybe is a bug on CoreAPI + len: u64: u64, + ), + (&BinaryView::from_raw(view), offset, len), +} +FunctionAdded => { + FunctionAddedHandler, + FunctionAddedDummy, + function_added_impl, + function_added_ffi, + functionAdded, + function_added( + view: *mut BNBinaryView: &BinaryView, + func: *mut BNFunction: &Function, + ), + (&BinaryView::from_raw(view), &Function::from_raw(func)), +} +FunctionRemoved => { + FunctionRemovedHandler, + FunctionRemovedDummy, + function_removed_impl, + function_removed_ffi, + functionRemoved, + function_removed( + view: *mut BNBinaryView: &BinaryView, + func: *mut BNFunction: &Function, + ), + (&BinaryView::from_raw(view), &Function::from_raw(func)), +} +FunctionUpdated => { + FunctionUpdatedHandler, + FunctionUpdatedDummy, + function_updated_impl, + function_updated_ffi, + functionUpdated, + function_updated( + view: *mut BNBinaryView: &BinaryView, + func: *mut BNFunction: &Function, + ), + (&BinaryView::from_raw(view), &Function::from_raw(func)), +} +FunctionUpdateRequested => { + FunctionUpdateRequestedHandler, + FunctionUpdateRequestedDummy, + function_update_requested_impl, + function_update_requested_ffi, + functionUpdateRequested, + function_update_requested( + view: *mut BNBinaryView: &BinaryView, + func: *mut BNFunction: &Function, + ), + (&BinaryView::from_raw(view), &Function::from_raw(func)), +} +DataVariableAdded => { + DataVariableAddedHandler, + DataVariableAddedDummy, + data_variable_added_impl, + data_variable_added_ffi, + dataVariableAdded, + data_variable_added( + view: *mut BNBinaryView: &BinaryView, + var: *mut BNDataVariable: &DataVariable, + ), + (&BinaryView::from_raw(view), &DataVariable::from_raw(&*var)), +} +DataVariableRemoved => { + DataVariableRemovedHandler, + DataVariableRemovedDummy, + data_variable_removed_impl, + data_variable_removed_ffi, + dataVariableRemoved, + data_variable_removed( + view: *mut BNBinaryView: &BinaryView, + var: *mut BNDataVariable: &DataVariable, + ), + (&BinaryView::from_raw(view), &DataVariable::from_raw(&*var)), +} +DataVariableUpdated => { + DataVariableUpdatedHandler, + DataVariableUpdatedDummy, + data_variable_updated_impl, + data_variable_updated_ffi, + dataVariableUpdated, + data_variable_updated( + view: *mut BNBinaryView: &BinaryView, + var: *mut BNDataVariable: &DataVariable, + ), + (&BinaryView::from_raw(view), &DataVariable::from_raw(&*var)), +} +DataMetadataUpdated => { + DataMetadataUpdatedHandler, + DataMetadataUpdatedDummy, + data_metadata_updated_impl, + data_metadata_updated_ffi, + dataMetadataUpdated, + data_metadata_updated( + view: *mut BNBinaryView: &BinaryView, + offset: u64: u64, + ), + (&BinaryView::from_raw(view), offset), +} +TagTypeUpdated => { + TagTypeUpdatedHandler, + TagTypeUpdatedDummy, + tag_type_updated_impl, + tag_type_updated_ffi, + tagTypeUpdated, + tag_type_updated( + view: *mut BNBinaryView: &BinaryView, + tag_type: *mut BNTagType: &TagType, + ), + (&BinaryView::from_raw(view), &TagType{ handle: tag_type }), +} +TagAdded => { + TagAddedHandler, + TagAddedDummy, + tag_added_impl, + tag_added_ffi, + tagAdded, + tag_added( + view: *mut BNBinaryView: &BinaryView, + tag_ref: *mut BNTagReference: &TagReference, + ), + (&BinaryView::from_raw(view), &TagReference::from(&*tag_ref)), +} +TagRemoved => { + TagRemovedHandler, + TagRemovedDummy, + tag_removed_impl, + tag_removed_ffi, + tagRemoved, + tag_removed( + view: *mut BNBinaryView: &BinaryView, + tag_ref: *mut BNTagReference: &TagReference, + ), + (&BinaryView::from_raw(view), &TagReference::from(&*tag_ref)), +} +TagUpdated => { + TagUpdatedHandler, + TagUpdatedDummy, + tag_updated_impl, + tag_updated_ffi, + tagUpdated, + tag_updated( + view: *mut BNBinaryView: &BinaryView, + tag_ref: *mut BNTagReference: &TagReference, + ), + (&BinaryView::from_raw(view), &TagReference::from(&*tag_ref)), +} +SymbolAdded => { + SymbolAddedHandler, + SymbolAddedDummy, + symbol_added_impl, + symbol_added_ffi, + symbolAdded, + symbol_added( + view: *mut BNBinaryView: &BinaryView, + sym: *mut BNSymbol: &Symbol, + ), + (&BinaryView::from_raw(view), &Symbol::from_raw(sym)), +} +SymbolRemoved => { + SymbolRemovedHandler, + SymbolRemovedDummy, + symbol_removed_impl, + symbol_removed_ffi, + symbolRemoved, + symbol_removed( + view: *mut BNBinaryView: &BinaryView, + sym: *mut BNSymbol: &Symbol, + ), + (&BinaryView::from_raw(view), &Symbol::from_raw(sym)), +} +SymbolUpdated => { + SymbolUpdatedHandler, + SymbolUpdatedDummy, + symbol_updated_impl, + symbol_updated_ffi, + symbolUpdated, + symbol_updated( + view: *mut BNBinaryView: &BinaryView, + sym: *mut BNSymbol: &Symbol, + ), + (&BinaryView::from_raw(view), &Symbol::from_raw(sym)), +} +StringFound => { + StringFoundHandler, + StringFoundDummy, + string_found_impl, + string_found_ffi, + stringFound, + string_found( + view: *mut BNBinaryView: &BinaryView, + type_: BNStringType: StringType, + offset: u64: u64, + len: usize: usize, + ), + (&BinaryView::from_raw(view), type_, offset, len), +} +StringRemoved => { + StringRemovedHandler, + StringRemovedDummy, + string_removed_impl, + string_removed_ffi, + stringRemoved, + string_removed( + view: *mut BNBinaryView: &BinaryView, + type_: BNStringType: StringType, + offset: u64: u64, + len: usize: usize, + ), + (&BinaryView::from_raw(view), type_, offset, len), +} +TypeDefined => { + TypeDefinedHandler, + TypeDefinedDummy, + type_defined_impl, + type_defined_ffi, + typeDefined, + type_defined( + view: *mut BNBinaryView: &BinaryView, + name: *mut BNQualifiedName: &QualifiedName, + type_: *mut BNType: &Type, + ), + (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), &Type::from_raw(type_)), +} +TypeUndefined => { + TypeUndefinedHandler, + TypeUndefinedDummy, + type_undefined_impl, + type_undefined_ffi, + typeUndefined, + type_undefined(view: *mut BNBinaryView: &BinaryView, + name: *mut BNQualifiedName: &QualifiedName, + type_: *mut BNType: &Type, + ), + (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), &Type::from_raw(type_)), +} +TypeReferenceChanged => { + TypeReferenceChangedHandler, + TypeReferenceChangedDummy, + type_reference_changed_impl, + type_reference_changed_ffi, + typeReferenceChanged, + type_reference_changed( + view: *mut BNBinaryView: &BinaryView, + name: *mut BNQualifiedName: &QualifiedName, + type_: *mut BNType: &Type, + ), + (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), &Type::from_raw(type_)), +} +TypeFieldReferenceChanged => { + TypeFieldReferenceChangedHandler, + TypeFieldReferenceChangedDummy, + type_field_reference_changed_impl, + type_field_reference_changed_ffi, + typeFieldReferenceChanged, + type_field_reference_changed( + view: *mut BNBinaryView: &BinaryView, + name: *mut BNQualifiedName: &QualifiedName, + offset: u64: u64, + ), + (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), offset), +} +SegmentAdded => { + SegmentAddedHandler, + SegmentAddedDummy, + segment_added_impl, + segment_added_ffi, + segmentAdded, + segment_added( + view: *mut BNBinaryView: &BinaryView, + segment: *mut BNSegment: &Segment, + ), + (&BinaryView::from_raw(view), &Segment::from_raw(segment)), +} +SegmentRemoved => { + SegmentRemovedHandler, + SegmentRemovedDummy, + segment_removed_impl, + segment_removed_ffi, + segmentRemoved, + segment_removed( + view: *mut BNBinaryView: &BinaryView, + segment: *mut BNSegment: &Segment, + ), + (&BinaryView::from_raw(view), &Segment::from_raw(segment)), +} +SegmentUpdated => { + SegmentUpdatedHandler, + SegmentUpdatedDummy, + segment_updated_impl, + segment_updated_ffi, + segmentUpdated, + segment_updated(view: *mut BNBinaryView: &BinaryView, + segment: *mut BNSegment: &Segment, + ), + (&BinaryView::from_raw(view), &Segment::from_raw(segment)), +} +SectionAdded => { + SectionAddedHandler, + SectionAddedDummy, + section_added_impl, + section_added_ffi, + sectionAdded, + section_added( + view: *mut BNBinaryView: &BinaryView, + section: *mut BNSection: &Section, + ), + (&BinaryView::from_raw(view), &Section::from_raw(section)), +} +SectionRemoved => { + SectionRemovedHandler, + SectionRemovedDummy, + section_removed_impl, + section_removed_ffi, + sectionRemoved, + section_removed( + view: *mut BNBinaryView: &BinaryView, + section: *mut BNSection: &Section, + ), + (&BinaryView::from_raw(view), &Section::from_raw(section)), +} +SectionUpdated => { + SectionUpdatedHandler, + SectionUpdatedDummy, + section_updated_impl, + section_updated_ffi, + sectionUpdated, + section_updated( + view: *mut BNBinaryView: &BinaryView, + section: *mut BNSection: &Section, + ), + (&BinaryView::from_raw(view), &Section::from_raw(section)), +} +ComponentNameUpdated => { + ComponentNameUpdatedHandler, + ComponentNameUpdatedDummy, + component_name_updated_impl, + component_name_updated_ffi, + componentNameUpdated, + component_name_updated( + view: *mut BNBinaryView: &BinaryView, + previous_name: *mut ::std::os::raw::c_char: &str, + component: *mut BNComponent: &Component, + ), + ( + &BinaryView::from_raw(view), + CStr::from_ptr(previous_name).to_str().unwrap(), + &Component::from_raw(ptr::NonNull::new(component).unwrap()) + ), +} +ComponentAdded => { + ComponentAddedHandler, + ComponentAddedDummy, + component_added_impl, + component_added_ffi, + componentAdded, + component_added( + view: *mut BNBinaryView: &BinaryView, + component: *mut BNComponent: &Component, + ), + (&BinaryView::from_raw(view), &Component::from_raw(ptr::NonNull::new(component).unwrap())), +} +ComponentMoved => { + ComponentMovedHandler, + ComponentMovedDummy, + component_moved_impl, + component_moved_ffi, + componentMoved, + component_moved( + view: *mut BNBinaryView: &BinaryView, + former_parent: *mut BNComponent: &Component, + new_parent: *mut BNComponent: &Component, + component: *mut BNComponent: &Component, + ), + ( + &BinaryView::from_raw(view), + &Component::from_raw(ptr::NonNull::new(former_parent).unwrap()), + &Component::from_raw(ptr::NonNull::new(new_parent).unwrap()), + &Component::from_raw(ptr::NonNull::new(component).unwrap()) + ), +} +ComponentRemoved => { + ComponentRemovedHandler, + ComponentRemovedDummy, + component_removed_impl, + component_removed_ffi, + componentRemoved, + component_removed(view: *mut BNBinaryView: &BinaryView, + former_parent: *mut BNComponent: &Component, + component: *mut BNComponent: &Component, + ), + ( + &BinaryView::from_raw(view), + &Component::from_raw(ptr::NonNull::new(former_parent).unwrap()), + &Component::from_raw(ptr::NonNull::new(component).unwrap()) + ), +} +ComponentFunctionAdded => { + ComponentFunctionAddedHandler, + ComponentFunctionAddedDummy, + component_function_added_impl, + component_function_added_ffi, + componentFunctionAdded, + component_function_added( + view: *mut BNBinaryView: &BinaryView, + component: *mut BNComponent: &Component, + function: *mut BNFunction: &Function, + ), + ( + &BinaryView::from_raw(view), + &Component::from_raw(ptr::NonNull::new(component).unwrap()), + &Function::from_raw(function) + ), +} +ComponentFunctionRemoved => { + ComponentFunctionRemovedHandler, + ComponentFunctionRemovedDummy, + component_function_removed_impl, + component_function_removed_ffi, + componentFunctionRemoved, + component_function_removed(view: *mut BNBinaryView: &BinaryView, + component: *mut BNComponent: &Component, + function: *mut BNFunction: &Function, + ), + ( + &BinaryView::from_raw(view), + &Component::from_raw(ptr::NonNull::new(component).unwrap()), + &Function::from_raw(function), + ), +} +ComponentDataVariableAdded => { + ComponentDataVariableAddedHandler, + ComponentDataVariableAddedDummy, + component_data_variable_added_impl, + component_data_variable_added_ffi, + componentDataVariableAdded, + component_data_variable_added( + view: *mut BNBinaryView: &BinaryView, + component: *mut BNComponent: &Component, + var: *mut BNDataVariable: &DataVariable, + ), + ( + &BinaryView::from_raw(view), + &Component::from_raw(ptr::NonNull::new(component).unwrap()), + &DataVariable::from_raw(&*var), + ), +} +ComponentDataVariableRemoved => { + ComponentDataVariableRemovedHandler, + ComponentDataVariableRemovedDummy, + component_data_variable_removed_impl, + component_data_variable_removed_ffi, + componentDataVariableRemoved, + component_data_variable_removed( + view: *mut BNBinaryView: &BinaryView, + component: *mut BNComponent: &Component, + var: *mut BNDataVariable: &DataVariable, + ), + ( + &BinaryView::from_raw(view), + &Component::from_raw(ptr::NonNull::new(component).unwrap()), + &DataVariable::from_raw(&*var), + ), +} +ExternalLibraryAdded => { + ExternalLibraryAddedHandler, + ExternalLibraryAddedDummy, + external_library_added_impl, + external_library_added_ffi, + externalLibraryAdded, + external_library_added( + data: *mut BNBinaryView: &BinaryView, + library: *mut BNExternalLibrary: &ExternalLibrary, + ), + ( + &BinaryView::from_raw(data), + &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()) + ), +} +ExternalLibraryUpdated => { + ExternalLibraryUpdatedHandler, + ExternalLibraryUpdatedDummy, + external_library_updated_impl, + external_library_updated_ffi, + externalLibraryUpdated, + external_library_updated( + data: *mut BNBinaryView: &BinaryView, + library: *mut BNExternalLibrary: &ExternalLibrary, + ), + ( + &BinaryView::from_raw(data), + &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()) + ), +} +ExternalLibraryRemoved => { + ExternalLibraryRemovedHandler, + ExternalLibraryRemovedDummy, + external_library_removed_impl, + external_library_removed_ffi, + externalLibraryRemoved, + external_library_removed( + data: *mut BNBinaryView: &BinaryView, + library: *mut BNExternalLibrary: &ExternalLibrary, + ), + ( + &BinaryView::from_raw(data), + &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()) + ), +} +ExternalLocationAdded => { + ExternalLocationAddedHandler, + ExternalLocationAddedDummy, + external_location_added_impl, + external_location_added_ffi, + externalLocationAdded, + external_location_added( + data: *mut BNBinaryView: &BinaryView, + location: *mut BNExternalLocation: &ExternalLocation, + ), + ( + &BinaryView::from_raw(data), + &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()) + ), +} +ExternalLocationUpdated => { + ExternalLocationUpdatedHandler, + ExternalLocationUpdatedDummy, + external_location_updated_impl, + external_location_updated_ffi, + externalLocationUpdated, + external_location_updated( + data: *mut BNBinaryView: &BinaryView, + location: *mut BNExternalLocation: &ExternalLocation, + ), + ( + &BinaryView::from_raw(data), + &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()) + ), +} +ExternalLocationRemoved => { + ExternalLocationRemovedHandler, + ExternalLocationRemovedDummy, + external_location_removed_impl, + external_location_removed_ffi, + externalLocationRemoved, + external_location_removed( + data: *mut BNBinaryView: &BinaryView, + location: *mut BNExternalLocation: &ExternalLocation, + ), + ( + &BinaryView::from_raw(data), + &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()) + ), +} +TypeArchiveAttached => { + TypeArchiveAttachedHandler, + TypeArchiveAttachedDummy, + type_archive_attached_impl, + type_archive_attached_ffi, + typeArchiveAttached, + type_archive_attached( + view: *mut BNBinaryView: &BinaryView, + id: *const ::std::os::raw::c_char: &str, + path: *const ::std::os::raw::c_char: &[u8], + ), + ( + &BinaryView::from_raw(view), + CStr::from_ptr(id).to_str().unwrap(), + CStr::from_ptr(path).to_bytes(), + ), +} +TypeArchiveDetached => { + TypeArchiveDetachedHandler, + TypeArchiveDetachedDummy, + type_archive_detached_impl, + type_archive_detached_ffi, + typeArchiveDetached, + type_archive_detached( + view: *mut BNBinaryView: &BinaryView, + id: *const ::std::os::raw::c_char: &str, + path: *const ::std::os::raw::c_char: &[u8], + ), + ( + &BinaryView::from_raw(view), + CStr::from_ptr(id).to_str().unwrap(), + CStr::from_ptr(path).to_bytes(), + ), +} +TypeArchiveConnected => { + TypeArchiveConnectedHandler, + TypeArchiveConnectedDummy, + type_archive_connected_impl, + type_archive_connected_ffi, + typeArchiveConnected, + type_archive_connected( + view: *mut BNBinaryView: &BinaryView, + archive: *mut BNTypeArchive: &TypeArchive, + ), + ( + &BinaryView::from_raw(view), + &TypeArchive::from_raw(ptr::NonNull::new(archive).unwrap()), + ), +} +TypeArchiveDisconnected => { + TypeArchiveDisconnectedHandler, + TypeArchiveDisconnectedDummy, + type_archive_disconnected_impl, + type_archive_disconnected_ffi, + typeArchiveDisconnected, + type_archive_disconnected( + view: *mut BNBinaryView: &BinaryView, + archive: *mut BNTypeArchive: &TypeArchive, + ), + ( + &BinaryView::from_raw(view), + &TypeArchive::from_raw(ptr::NonNull::new(archive).unwrap()), + ), +} +UndoEntryAdded => { + UndoEntryAddedHandler, + UndoEntryAddedDummy, + undo_entry_added_impl, + undo_entry_added_ffi, + undoEntryAdded, + undo_entry_added( + view: *mut BNBinaryView: &BinaryView, + entry: *mut BNUndoEntry: &UndoEntry, + ), + ( + &BinaryView::from_raw(view), + &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), + ), +} +UndoEntryTaken => { + UndoEntryTakenHandler, + UndoEntryTakenDummy, + undo_entry_taken_impl, + undo_entry_taken_ffi, + undoEntryTaken, + undo_entry_taken( + view: *mut BNBinaryView: &BinaryView, + entry: *mut BNUndoEntry: &UndoEntry, + ), + ( + &BinaryView::from_raw(view), + &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), + ), +} +RedoEntryTaken => { + RedoEntryTakenHandler, + RedoEntryTakenDummy, + redo_entry_taken_impl, + redo_entry_taken_ffi, + redoEntryTaken, + redo_entry_taken( + view: *mut BNBinaryView: &BinaryView, + entry: *mut BNUndoEntry: &UndoEntry, + ), + ( + &BinaryView::from_raw(view), + &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), + ), +} +Rebased => { + RebasedHandler, + RebasedDummy, + rebased_impl, + rebased_ffi, + rebased, + rebased( + oldview: *mut BNBinaryView: &BinaryView, + newview: *mut BNBinaryView: &BinaryView, + ), + (&BinaryView::from_raw(oldview), &BinaryView::from_raw(newview)), +}); + +pub struct DataNotificationHandle<'a, T: CustomDataNotification> +where + T: 'a, +{ + bv: Ref, + handle: BNBinaryDataNotification, + _life: std::marker::PhantomData<&'a T>, +} + +impl DataNotificationHandle<'_, T> { + unsafe fn unregister_bv(&mut self) { + BNUnregisterDataNotification(self.bv.handle, &mut self.handle) + } + + unsafe fn extract_context(&mut self) -> Box { + Box::from_raw(self.handle.context as *mut T) + } + + pub fn unregister(self) -> T { + // NOTE don't drop the ctxt, return it + let mut slf = core::mem::ManuallyDrop::new(self); + unsafe { slf.unregister_bv() }; + unsafe { *slf.extract_context() } + } +} + +impl Drop for DataNotificationHandle<'_, T> { + fn drop(&mut self) { + unsafe { self.unregister_bv() }; + // drop context, avoid memory leak + let _ctxt = unsafe { self.extract_context() }; + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a3df0cd35..a3d9c6bfe 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -42,6 +42,7 @@ pub mod component; pub mod confidence; pub mod custom_binary_view; pub mod data_buffer; +pub mod data_notification; pub mod database; pub mod debuginfo; pub mod demangle; diff --git a/rust/src/section.rs b/rust/src/section.rs index c88ef9b0e..67f3e8653 100644 --- a/rust/src/section.rs +++ b/rust/src/section.rs @@ -68,7 +68,7 @@ pub struct Section { } impl Section { - unsafe fn from_raw(handle: *mut BNSection) -> Self { + pub(crate) unsafe fn from_raw(handle: *mut BNSection) -> Self { debug_assert!(!handle.is_null()); Self { handle } } diff --git a/rust/tests/data_notification.rs b/rust/tests/data_notification.rs new file mode 100644 index 000000000..dd4c783a0 --- /dev/null +++ b/rust/tests/data_notification.rs @@ -0,0 +1,131 @@ +use std::path::PathBuf; + +use binaryninja::binary_view::{BinaryView, BinaryViewExt}; +use binaryninja::data_notification::*; +use binaryninja::function::Function; +use binaryninja::headless::Session; +use binaryninja::tags::TagReference; + +#[test] +fn test_data_notification_dyn_closure() { + let _session = Session::new().expect("Failed to initialize session"); + let out_dir = env!("OUT_DIR").parse::().unwrap(); + let bv = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view"); + + let mut func_updated_count = 0usize; + let custom = DataNotificationClosure::default() + .function_updated(|_bv: &BinaryView, _func: &Function| { + func_updated_count += 1; + }) + .register(&bv); + + let funcs = bv.functions(); + for func in &funcs { + let crash = bv.create_tag_type("Test", "🚧"); + func.add_tag( + &crash, + "Dummy tag", + Some(10.try_into().unwrap()), + true, + None, + ); + } + custom.unregister(); + + assert_eq!(funcs.len(), func_updated_count); +} + +#[test] +fn test_data_notification_impl() { + let _session = Session::new().expect("Failed to initialize session"); + let out_dir = env!("OUT_DIR").parse::().unwrap(); + let bv = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view"); + + #[derive(Default)] + struct Tag { + tags: usize, + } + + impl CustomDataNotification for Tag { + // unfortunately rust is not able to fill those types automatically + // this will probably only be possible after the feature + // associated_type_defaults is merged: + // https://github.com/rust-lang/rust/issues/29661 + type NotificationBarrier = NotificationBarrierDummy; + type DataWritten = DataWrittenDummy; + type DataInserted = DataInsertedDummy; + type DataRemoved = DataRemovedDummy; + type FunctionAdded = FunctionAddedDummy; + type FunctionRemoved = FunctionRemovedDummy; + type FunctionUpdated = FunctionUpdatedDummy; + type FunctionUpdateRequested = FunctionUpdateRequestedDummy; + type DataVariableAdded = DataVariableAddedDummy; + type DataVariableRemoved = DataVariableRemovedDummy; + type DataVariableUpdated = DataVariableUpdatedDummy; + type DataMetadataUpdated = DataMetadataUpdatedDummy; + type TagTypeUpdated = TagTypeUpdatedDummy; + type TagUpdated = TagUpdatedDummy; + type TagRemoved = TagRemovedDummy; + type SymbolAdded = SymbolAddedDummy; + type SymbolRemoved = SymbolRemovedDummy; + type SymbolUpdated = SymbolUpdatedDummy; + type StringFound = StringFoundDummy; + type StringRemoved = StringRemovedDummy; + type TypeDefined = TypeDefinedDummy; + type TypeUndefined = TypeUndefinedDummy; + type TypeReferenceChanged = TypeReferenceChangedDummy; + type TypeFieldReferenceChanged = TypeFieldReferenceChangedDummy; + type SegmentAdded = SegmentAddedDummy; + type SegmentRemoved = SegmentRemovedDummy; + type SegmentUpdated = SegmentUpdatedDummy; + type SectionAdded = SectionAddedDummy; + type SectionRemoved = SectionRemovedDummy; + type SectionUpdated = SectionUpdatedDummy; + type ComponentNameUpdated = ComponentNameUpdatedDummy; + type ComponentAdded = ComponentAddedDummy; + type ComponentMoved = ComponentMovedDummy; + type ComponentRemoved = ComponentRemovedDummy; + type ComponentFunctionAdded = ComponentFunctionAddedDummy; + type ComponentFunctionRemoved = ComponentFunctionRemovedDummy; + type ComponentDataVariableAdded = ComponentDataVariableAddedDummy; + type ComponentDataVariableRemoved = ComponentDataVariableRemovedDummy; + type ExternalLibraryAdded = ExternalLibraryAddedDummy; + type ExternalLibraryUpdated = ExternalLibraryUpdatedDummy; + type ExternalLibraryRemoved = ExternalLibraryRemovedDummy; + type ExternalLocationAdded = ExternalLocationAddedDummy; + type ExternalLocationUpdated = ExternalLocationUpdatedDummy; + type ExternalLocationRemoved = ExternalLocationRemovedDummy; + type TypeArchiveAttached = TypeArchiveAttachedDummy; + type TypeArchiveDetached = TypeArchiveDetachedDummy; + type TypeArchiveConnected = TypeArchiveConnectedDummy; + type TypeArchiveDisconnected = TypeArchiveDisconnectedDummy; + type UndoEntryAdded = UndoEntryAddedDummy; + type UndoEntryTaken = UndoEntryTakenDummy; + type RedoEntryTaken = RedoEntryTakenDummy; + type Rebased = RebasedDummy; + + type TagAdded = Self; + + fn tag_added_impl(&mut self) -> Option<&mut Self> { + Some(self) + } + } + + impl TagAddedHandler for Tag { + fn tag_added(&mut self, _view: &BinaryView, _tag_ref: &TagReference) { + self.tags += 1; + } + } + + let tags_lock = Tag::default().register(&bv); + + let funcs = bv.functions(); + for (i, func) in funcs.iter().enumerate() { + let crash = bv.create_tag_type("Test", "🚧"); + func.add_tag(&crash, "Dummy tag", Some(i.try_into().unwrap()), true, None); + } + + let tags = tags_lock.unregister(); + + assert_eq!(funcs.len(), tags.tags); +} From 98bd09b237cfd9213c423097c4326aba941bf901 Mon Sep 17 00:00:00 2001 From: rbran Date: Thu, 3 Apr 2025 11:31:07 +0000 Subject: [PATCH 2/4] simplify data notification rust implementation --- rust/src/data_notification.rs | 1066 +++++++++---------------------- rust/tests/data_notification.rs | 68 +- 2 files changed, 287 insertions(+), 847 deletions(-) diff --git a/rust/src/data_notification.rs b/rust/src/data_notification.rs index 049b2d40c..b617d380c 100644 --- a/rust/src/data_notification.rs +++ b/rust/src/data_notification.rs @@ -27,76 +27,64 @@ use crate::variable::DataVariable; macro_rules! trait_handler { ( $( - $type_name:ident => { - $trait_name:ident, - $dummy_impl_name:ident, - $impl_fun_name:ident, - $ffi_fun_name:ident, - $ffi_param_name:ident, - $fun_name:ident($($arg_name:ident : $raw_arg_type:ty : $arg_type:ty),* $(,)?) $(-> $ret_type:ty)?, - ($($value_calculated:expr),* $(,)?) - $(,)? - } $(,)? - )* + $ffi_param_name:ident => $fun_name:ident( + $( + $arg_name:ident: + $raw_arg_type:ty: + $arg_type:ty = + $value_calculated:expr + ),* $(,)? + ) $(-> $ret_type:ty)? + ),* $(,)? ) => { + #[derive(Default)] + pub struct DataNotificationTriggers { + $($fun_name: bool,)* + } + impl DataNotificationTriggers { + $( + pub fn $fun_name(mut self) -> Self { + self.$fun_name = true; + self + } + )* + } pub trait CustomDataNotification: Sync + Send { - $(type $type_name: $trait_name;)* - // TODO once this becomes stable add a default type impl - // https://github.com/rust-lang/rust/issues/29661 - //$(type $type_name: $trait_name = $dummy_impl_name;)* - $( #[inline] - fn $impl_fun_name(&mut self) -> Option<&mut Self::$type_name> { - None + #[allow(unused_variables)] + fn $fun_name(&mut self, $($arg_name: $arg_type),*) $(-> $ret_type)* { + $( <$ret_type as Default>::default() )* } )* - fn register<'a>(self, view: &BinaryView) -> DataNotificationHandle<'a, Self> where Self: 'a + Sized { - register_data_notification(view, self) + fn register<'a>( + self, + view: &BinaryView, + triggers: DataNotificationTriggers, + ) -> DataNotificationHandle<'a, Self> where Self: 'a + Sized { + register_data_notification(view, self, triggers) } } $( - pub trait $trait_name { - fn $fun_name(&mut self, $($arg_name: $arg_type),*) $(-> $ret_type)*; - } - - pub struct $dummy_impl_name; - impl $trait_name for $dummy_impl_name { - #[allow(unused_variables)] - fn $fun_name(&mut self, $($arg_name: $arg_type),*) $(-> $ret_type)* { - $( - const RET_VALUE: $ret_type = 0; - RET_VALUE - )* - } - } - - unsafe extern "C" fn $ffi_fun_name( + unsafe extern "C" fn $fun_name( ctxt: *mut ::std::os::raw::c_void, $($arg_name: $raw_arg_type),* ) $(-> $ret_type)* { let handle: &mut H = &mut *(ctxt as *mut H); - let Some(callback) = handle.$impl_fun_name() else { - unreachable!(); - }; - callback.$fun_name($($value_calculated),*) + handle.$fun_name($($value_calculated),*) } )* pub fn register_data_notification<'a, H: CustomDataNotification + 'a>( view: &BinaryView, notify: H, + triggers: DataNotificationTriggers, ) -> DataNotificationHandle<'a, H> { // SAFETY: this leak is undone on drop let leak_notify = Box::leak(Box::new(notify)); let mut handle = BNBinaryDataNotification { context: leak_notify as *mut _ as *mut ffi::c_void, - $( - $ffi_param_name: leak_notify - .$impl_fun_name() - .is_some() - .then_some($ffi_fun_name::), - )* + $($ffi_param_name: triggers.$fun_name.then_some($fun_name::)),* }; unsafe { BNRegisterDataNotification(view.handle, &mut handle) }; DataNotificationHandle { @@ -108,7 +96,9 @@ macro_rules! trait_handler { pub struct DataNotificationClosure<'a> { $( - $fun_name: Option $ret_type)* + Sync + Send + 'a>>, + $fun_name: Option $ret_type)* + Sync + Send + 'a + >>, )* } @@ -123,762 +113,276 @@ macro_rules! trait_handler { Default::default() } $( - pub fn $fun_name $ret_type)* + Sync + Send + 'a>(mut self, param: F) -> Self { + pub fn $fun_name $ret_type)* + Sync + Send + 'a>(mut self, param: F) -> Self { self.$fun_name = Some(Box::new(param)); self } )* - pub fn register(self, view: &BinaryView) -> DataNotificationHandle<'a, Self> { - register_data_notification(view, self) + pub fn register( + self, + view: &BinaryView, + ) -> DataNotificationHandle<'a, Self> { + let mut triggers = DataNotificationTriggers::default(); + $( + if self.$fun_name.is_some() { + triggers = triggers.$fun_name(); + } + )* + register_data_notification(view, self, triggers) } } impl CustomDataNotification for DataNotificationClosure<'_> { $( - type $type_name = Self; - fn $impl_fun_name(&mut self) -> Option<&mut Self::$type_name> { - self.$fun_name.is_some().then_some(self) - } - )* - } - - $( - impl $trait_name for DataNotificationClosure<'_> { fn $fun_name(&mut self, $($arg_name: $arg_type),*) $(-> $ret_type)* { let Some(handle) = self.$fun_name.as_mut() else { unreachable!(); }; handle($($arg_name),*) } - } )* - - }; + } +}; } -trait_handler!( -NotificationBarrier => { - NotificationBarrierHandler, - NotificationBarrierDummy, - notification_barrier_impl, - notification_barrier_ffi, - notificationBarrier, - notification_barrier(view: *mut BNBinaryView: &BinaryView) -> u64, - (&BinaryView::from_raw(view)), -} -DataWritten => { - DataWrittenHandler, - DataWrittenDummy, - data_written_impl, - data_written_ffi, - dataWritten, - data_written( - view: *mut BNBinaryView: &BinaryView, - offset: u64: u64, - len: usize: usize, - ), - (&BinaryView::from_raw(view), offset, len), -} -DataInserted => { - DataInsertedHandler, - DataInsertedDummy, - data_inserted_impl, - data_inserted_ffi, - dataInserted, - data_inserted( - view: *mut BNBinaryView: &BinaryView, - offset: u64: u64, - len: usize: usize, - ), - (&BinaryView::from_raw(view), offset, len), -} -DataRemoved => { - DataRemovedHandler, - DataRemovedDummy, - data_removed_impl, - data_removed_ffi, - dataRemoved, - data_removed( - view: *mut BNBinaryView: &BinaryView, - offset: u64: u64, +trait_handler! { + notificationBarrier => notification_barrier( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + ) -> u64, + dataWritten => data_written( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + offset: u64: u64 = offset, + len: usize: usize = len, + ), + dataInserted => data_inserted( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + offset: u64: u64 = offset, + len: usize: usize = len, + ), + dataRemoved => data_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + offset: u64: u64 = offset, // TODO why the len is u64 here? Maybe is a bug on CoreAPI - len: u64: u64, - ), - (&BinaryView::from_raw(view), offset, len), -} -FunctionAdded => { - FunctionAddedHandler, - FunctionAddedDummy, - function_added_impl, - function_added_ffi, - functionAdded, - function_added( - view: *mut BNBinaryView: &BinaryView, - func: *mut BNFunction: &Function, - ), - (&BinaryView::from_raw(view), &Function::from_raw(func)), -} -FunctionRemoved => { - FunctionRemovedHandler, - FunctionRemovedDummy, - function_removed_impl, - function_removed_ffi, - functionRemoved, - function_removed( - view: *mut BNBinaryView: &BinaryView, - func: *mut BNFunction: &Function, - ), - (&BinaryView::from_raw(view), &Function::from_raw(func)), -} -FunctionUpdated => { - FunctionUpdatedHandler, - FunctionUpdatedDummy, - function_updated_impl, - function_updated_ffi, - functionUpdated, - function_updated( - view: *mut BNBinaryView: &BinaryView, - func: *mut BNFunction: &Function, - ), - (&BinaryView::from_raw(view), &Function::from_raw(func)), -} -FunctionUpdateRequested => { - FunctionUpdateRequestedHandler, - FunctionUpdateRequestedDummy, - function_update_requested_impl, - function_update_requested_ffi, - functionUpdateRequested, - function_update_requested( - view: *mut BNBinaryView: &BinaryView, - func: *mut BNFunction: &Function, - ), - (&BinaryView::from_raw(view), &Function::from_raw(func)), -} -DataVariableAdded => { - DataVariableAddedHandler, - DataVariableAddedDummy, - data_variable_added_impl, - data_variable_added_ffi, - dataVariableAdded, - data_variable_added( - view: *mut BNBinaryView: &BinaryView, - var: *mut BNDataVariable: &DataVariable, - ), - (&BinaryView::from_raw(view), &DataVariable::from_raw(&*var)), -} -DataVariableRemoved => { - DataVariableRemovedHandler, - DataVariableRemovedDummy, - data_variable_removed_impl, - data_variable_removed_ffi, - dataVariableRemoved, - data_variable_removed( - view: *mut BNBinaryView: &BinaryView, - var: *mut BNDataVariable: &DataVariable, - ), - (&BinaryView::from_raw(view), &DataVariable::from_raw(&*var)), -} -DataVariableUpdated => { - DataVariableUpdatedHandler, - DataVariableUpdatedDummy, - data_variable_updated_impl, - data_variable_updated_ffi, - dataVariableUpdated, - data_variable_updated( - view: *mut BNBinaryView: &BinaryView, - var: *mut BNDataVariable: &DataVariable, - ), - (&BinaryView::from_raw(view), &DataVariable::from_raw(&*var)), -} -DataMetadataUpdated => { - DataMetadataUpdatedHandler, - DataMetadataUpdatedDummy, - data_metadata_updated_impl, - data_metadata_updated_ffi, - dataMetadataUpdated, - data_metadata_updated( - view: *mut BNBinaryView: &BinaryView, - offset: u64: u64, - ), - (&BinaryView::from_raw(view), offset), -} -TagTypeUpdated => { - TagTypeUpdatedHandler, - TagTypeUpdatedDummy, - tag_type_updated_impl, - tag_type_updated_ffi, - tagTypeUpdated, - tag_type_updated( - view: *mut BNBinaryView: &BinaryView, - tag_type: *mut BNTagType: &TagType, - ), - (&BinaryView::from_raw(view), &TagType{ handle: tag_type }), -} -TagAdded => { - TagAddedHandler, - TagAddedDummy, - tag_added_impl, - tag_added_ffi, - tagAdded, - tag_added( - view: *mut BNBinaryView: &BinaryView, - tag_ref: *mut BNTagReference: &TagReference, - ), - (&BinaryView::from_raw(view), &TagReference::from(&*tag_ref)), -} -TagRemoved => { - TagRemovedHandler, - TagRemovedDummy, - tag_removed_impl, - tag_removed_ffi, - tagRemoved, - tag_removed( - view: *mut BNBinaryView: &BinaryView, - tag_ref: *mut BNTagReference: &TagReference, - ), - (&BinaryView::from_raw(view), &TagReference::from(&*tag_ref)), -} -TagUpdated => { - TagUpdatedHandler, - TagUpdatedDummy, - tag_updated_impl, - tag_updated_ffi, - tagUpdated, - tag_updated( - view: *mut BNBinaryView: &BinaryView, - tag_ref: *mut BNTagReference: &TagReference, - ), - (&BinaryView::from_raw(view), &TagReference::from(&*tag_ref)), -} -SymbolAdded => { - SymbolAddedHandler, - SymbolAddedDummy, - symbol_added_impl, - symbol_added_ffi, - symbolAdded, - symbol_added( - view: *mut BNBinaryView: &BinaryView, - sym: *mut BNSymbol: &Symbol, - ), - (&BinaryView::from_raw(view), &Symbol::from_raw(sym)), -} -SymbolRemoved => { - SymbolRemovedHandler, - SymbolRemovedDummy, - symbol_removed_impl, - symbol_removed_ffi, - symbolRemoved, - symbol_removed( - view: *mut BNBinaryView: &BinaryView, - sym: *mut BNSymbol: &Symbol, - ), - (&BinaryView::from_raw(view), &Symbol::from_raw(sym)), -} -SymbolUpdated => { - SymbolUpdatedHandler, - SymbolUpdatedDummy, - symbol_updated_impl, - symbol_updated_ffi, - symbolUpdated, - symbol_updated( - view: *mut BNBinaryView: &BinaryView, - sym: *mut BNSymbol: &Symbol, - ), - (&BinaryView::from_raw(view), &Symbol::from_raw(sym)), -} -StringFound => { - StringFoundHandler, - StringFoundDummy, - string_found_impl, - string_found_ffi, - stringFound, - string_found( - view: *mut BNBinaryView: &BinaryView, - type_: BNStringType: StringType, - offset: u64: u64, - len: usize: usize, - ), - (&BinaryView::from_raw(view), type_, offset, len), -} -StringRemoved => { - StringRemovedHandler, - StringRemovedDummy, - string_removed_impl, - string_removed_ffi, - stringRemoved, - string_removed( - view: *mut BNBinaryView: &BinaryView, - type_: BNStringType: StringType, - offset: u64: u64, - len: usize: usize, - ), - (&BinaryView::from_raw(view), type_, offset, len), -} -TypeDefined => { - TypeDefinedHandler, - TypeDefinedDummy, - type_defined_impl, - type_defined_ffi, - typeDefined, - type_defined( - view: *mut BNBinaryView: &BinaryView, - name: *mut BNQualifiedName: &QualifiedName, - type_: *mut BNType: &Type, - ), - (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), &Type::from_raw(type_)), -} -TypeUndefined => { - TypeUndefinedHandler, - TypeUndefinedDummy, - type_undefined_impl, - type_undefined_ffi, - typeUndefined, - type_undefined(view: *mut BNBinaryView: &BinaryView, - name: *mut BNQualifiedName: &QualifiedName, - type_: *mut BNType: &Type, - ), - (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), &Type::from_raw(type_)), -} -TypeReferenceChanged => { - TypeReferenceChangedHandler, - TypeReferenceChangedDummy, - type_reference_changed_impl, - type_reference_changed_ffi, - typeReferenceChanged, - type_reference_changed( - view: *mut BNBinaryView: &BinaryView, - name: *mut BNQualifiedName: &QualifiedName, - type_: *mut BNType: &Type, - ), - (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), &Type::from_raw(type_)), -} -TypeFieldReferenceChanged => { - TypeFieldReferenceChangedHandler, - TypeFieldReferenceChangedDummy, - type_field_reference_changed_impl, - type_field_reference_changed_ffi, - typeFieldReferenceChanged, - type_field_reference_changed( - view: *mut BNBinaryView: &BinaryView, - name: *mut BNQualifiedName: &QualifiedName, - offset: u64: u64, - ), - (&BinaryView::from_raw(view), &QualifiedName::from_raw(&*name), offset), -} -SegmentAdded => { - SegmentAddedHandler, - SegmentAddedDummy, - segment_added_impl, - segment_added_ffi, - segmentAdded, - segment_added( - view: *mut BNBinaryView: &BinaryView, - segment: *mut BNSegment: &Segment, - ), - (&BinaryView::from_raw(view), &Segment::from_raw(segment)), -} -SegmentRemoved => { - SegmentRemovedHandler, - SegmentRemovedDummy, - segment_removed_impl, - segment_removed_ffi, - segmentRemoved, - segment_removed( - view: *mut BNBinaryView: &BinaryView, - segment: *mut BNSegment: &Segment, - ), - (&BinaryView::from_raw(view), &Segment::from_raw(segment)), -} -SegmentUpdated => { - SegmentUpdatedHandler, - SegmentUpdatedDummy, - segment_updated_impl, - segment_updated_ffi, - segmentUpdated, - segment_updated(view: *mut BNBinaryView: &BinaryView, - segment: *mut BNSegment: &Segment, - ), - (&BinaryView::from_raw(view), &Segment::from_raw(segment)), -} -SectionAdded => { - SectionAddedHandler, - SectionAddedDummy, - section_added_impl, - section_added_ffi, - sectionAdded, - section_added( - view: *mut BNBinaryView: &BinaryView, - section: *mut BNSection: &Section, - ), - (&BinaryView::from_raw(view), &Section::from_raw(section)), -} -SectionRemoved => { - SectionRemovedHandler, - SectionRemovedDummy, - section_removed_impl, - section_removed_ffi, - sectionRemoved, - section_removed( - view: *mut BNBinaryView: &BinaryView, - section: *mut BNSection: &Section, - ), - (&BinaryView::from_raw(view), &Section::from_raw(section)), -} -SectionUpdated => { - SectionUpdatedHandler, - SectionUpdatedDummy, - section_updated_impl, - section_updated_ffi, - sectionUpdated, - section_updated( - view: *mut BNBinaryView: &BinaryView, - section: *mut BNSection: &Section, - ), - (&BinaryView::from_raw(view), &Section::from_raw(section)), -} -ComponentNameUpdated => { - ComponentNameUpdatedHandler, - ComponentNameUpdatedDummy, - component_name_updated_impl, - component_name_updated_ffi, - componentNameUpdated, - component_name_updated( - view: *mut BNBinaryView: &BinaryView, - previous_name: *mut ::std::os::raw::c_char: &str, - component: *mut BNComponent: &Component, - ), - ( - &BinaryView::from_raw(view), - CStr::from_ptr(previous_name).to_str().unwrap(), - &Component::from_raw(ptr::NonNull::new(component).unwrap()) - ), -} -ComponentAdded => { - ComponentAddedHandler, - ComponentAddedDummy, - component_added_impl, - component_added_ffi, - componentAdded, - component_added( - view: *mut BNBinaryView: &BinaryView, - component: *mut BNComponent: &Component, - ), - (&BinaryView::from_raw(view), &Component::from_raw(ptr::NonNull::new(component).unwrap())), -} -ComponentMoved => { - ComponentMovedHandler, - ComponentMovedDummy, - component_moved_impl, - component_moved_ffi, - componentMoved, - component_moved( - view: *mut BNBinaryView: &BinaryView, - former_parent: *mut BNComponent: &Component, - new_parent: *mut BNComponent: &Component, - component: *mut BNComponent: &Component, - ), - ( - &BinaryView::from_raw(view), - &Component::from_raw(ptr::NonNull::new(former_parent).unwrap()), - &Component::from_raw(ptr::NonNull::new(new_parent).unwrap()), - &Component::from_raw(ptr::NonNull::new(component).unwrap()) - ), -} -ComponentRemoved => { - ComponentRemovedHandler, - ComponentRemovedDummy, - component_removed_impl, - component_removed_ffi, - componentRemoved, - component_removed(view: *mut BNBinaryView: &BinaryView, - former_parent: *mut BNComponent: &Component, - component: *mut BNComponent: &Component, - ), - ( - &BinaryView::from_raw(view), - &Component::from_raw(ptr::NonNull::new(former_parent).unwrap()), - &Component::from_raw(ptr::NonNull::new(component).unwrap()) - ), -} -ComponentFunctionAdded => { - ComponentFunctionAddedHandler, - ComponentFunctionAddedDummy, - component_function_added_impl, - component_function_added_ffi, - componentFunctionAdded, - component_function_added( - view: *mut BNBinaryView: &BinaryView, - component: *mut BNComponent: &Component, - function: *mut BNFunction: &Function, - ), - ( - &BinaryView::from_raw(view), - &Component::from_raw(ptr::NonNull::new(component).unwrap()), - &Function::from_raw(function) - ), -} -ComponentFunctionRemoved => { - ComponentFunctionRemovedHandler, - ComponentFunctionRemovedDummy, - component_function_removed_impl, - component_function_removed_ffi, - componentFunctionRemoved, - component_function_removed(view: *mut BNBinaryView: &BinaryView, - component: *mut BNComponent: &Component, - function: *mut BNFunction: &Function, - ), - ( - &BinaryView::from_raw(view), - &Component::from_raw(ptr::NonNull::new(component).unwrap()), - &Function::from_raw(function), - ), -} -ComponentDataVariableAdded => { - ComponentDataVariableAddedHandler, - ComponentDataVariableAddedDummy, - component_data_variable_added_impl, - component_data_variable_added_ffi, - componentDataVariableAdded, - component_data_variable_added( - view: *mut BNBinaryView: &BinaryView, - component: *mut BNComponent: &Component, - var: *mut BNDataVariable: &DataVariable, - ), - ( - &BinaryView::from_raw(view), - &Component::from_raw(ptr::NonNull::new(component).unwrap()), - &DataVariable::from_raw(&*var), - ), -} -ComponentDataVariableRemoved => { - ComponentDataVariableRemovedHandler, - ComponentDataVariableRemovedDummy, - component_data_variable_removed_impl, - component_data_variable_removed_ffi, - componentDataVariableRemoved, - component_data_variable_removed( - view: *mut BNBinaryView: &BinaryView, - component: *mut BNComponent: &Component, - var: *mut BNDataVariable: &DataVariable, - ), - ( - &BinaryView::from_raw(view), - &Component::from_raw(ptr::NonNull::new(component).unwrap()), - &DataVariable::from_raw(&*var), - ), -} -ExternalLibraryAdded => { - ExternalLibraryAddedHandler, - ExternalLibraryAddedDummy, - external_library_added_impl, - external_library_added_ffi, - externalLibraryAdded, - external_library_added( - data: *mut BNBinaryView: &BinaryView, - library: *mut BNExternalLibrary: &ExternalLibrary, - ), - ( - &BinaryView::from_raw(data), - &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()) - ), -} -ExternalLibraryUpdated => { - ExternalLibraryUpdatedHandler, - ExternalLibraryUpdatedDummy, - external_library_updated_impl, - external_library_updated_ffi, - externalLibraryUpdated, - external_library_updated( - data: *mut BNBinaryView: &BinaryView, - library: *mut BNExternalLibrary: &ExternalLibrary, - ), - ( - &BinaryView::from_raw(data), - &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()) - ), -} -ExternalLibraryRemoved => { - ExternalLibraryRemovedHandler, - ExternalLibraryRemovedDummy, - external_library_removed_impl, - external_library_removed_ffi, - externalLibraryRemoved, - external_library_removed( - data: *mut BNBinaryView: &BinaryView, - library: *mut BNExternalLibrary: &ExternalLibrary, - ), - ( - &BinaryView::from_raw(data), - &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()) - ), -} -ExternalLocationAdded => { - ExternalLocationAddedHandler, - ExternalLocationAddedDummy, - external_location_added_impl, - external_location_added_ffi, - externalLocationAdded, - external_location_added( - data: *mut BNBinaryView: &BinaryView, - location: *mut BNExternalLocation: &ExternalLocation, - ), - ( - &BinaryView::from_raw(data), - &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()) - ), -} -ExternalLocationUpdated => { - ExternalLocationUpdatedHandler, - ExternalLocationUpdatedDummy, - external_location_updated_impl, - external_location_updated_ffi, - externalLocationUpdated, - external_location_updated( - data: *mut BNBinaryView: &BinaryView, - location: *mut BNExternalLocation: &ExternalLocation, - ), - ( - &BinaryView::from_raw(data), - &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()) - ), -} -ExternalLocationRemoved => { - ExternalLocationRemovedHandler, - ExternalLocationRemovedDummy, - external_location_removed_impl, - external_location_removed_ffi, - externalLocationRemoved, - external_location_removed( - data: *mut BNBinaryView: &BinaryView, - location: *mut BNExternalLocation: &ExternalLocation, - ), - ( - &BinaryView::from_raw(data), - &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()) - ), -} -TypeArchiveAttached => { - TypeArchiveAttachedHandler, - TypeArchiveAttachedDummy, - type_archive_attached_impl, - type_archive_attached_ffi, - typeArchiveAttached, - type_archive_attached( - view: *mut BNBinaryView: &BinaryView, - id: *const ::std::os::raw::c_char: &str, - path: *const ::std::os::raw::c_char: &[u8], - ), - ( - &BinaryView::from_raw(view), - CStr::from_ptr(id).to_str().unwrap(), - CStr::from_ptr(path).to_bytes(), - ), -} -TypeArchiveDetached => { - TypeArchiveDetachedHandler, - TypeArchiveDetachedDummy, - type_archive_detached_impl, - type_archive_detached_ffi, - typeArchiveDetached, - type_archive_detached( - view: *mut BNBinaryView: &BinaryView, - id: *const ::std::os::raw::c_char: &str, - path: *const ::std::os::raw::c_char: &[u8], - ), - ( - &BinaryView::from_raw(view), - CStr::from_ptr(id).to_str().unwrap(), - CStr::from_ptr(path).to_bytes(), - ), -} -TypeArchiveConnected => { - TypeArchiveConnectedHandler, - TypeArchiveConnectedDummy, - type_archive_connected_impl, - type_archive_connected_ffi, - typeArchiveConnected, - type_archive_connected( - view: *mut BNBinaryView: &BinaryView, - archive: *mut BNTypeArchive: &TypeArchive, - ), - ( - &BinaryView::from_raw(view), - &TypeArchive::from_raw(ptr::NonNull::new(archive).unwrap()), - ), -} -TypeArchiveDisconnected => { - TypeArchiveDisconnectedHandler, - TypeArchiveDisconnectedDummy, - type_archive_disconnected_impl, - type_archive_disconnected_ffi, - typeArchiveDisconnected, - type_archive_disconnected( - view: *mut BNBinaryView: &BinaryView, - archive: *mut BNTypeArchive: &TypeArchive, - ), - ( - &BinaryView::from_raw(view), - &TypeArchive::from_raw(ptr::NonNull::new(archive).unwrap()), - ), -} -UndoEntryAdded => { - UndoEntryAddedHandler, - UndoEntryAddedDummy, - undo_entry_added_impl, - undo_entry_added_ffi, - undoEntryAdded, - undo_entry_added( - view: *mut BNBinaryView: &BinaryView, - entry: *mut BNUndoEntry: &UndoEntry, - ), - ( - &BinaryView::from_raw(view), - &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), - ), -} -UndoEntryTaken => { - UndoEntryTakenHandler, - UndoEntryTakenDummy, - undo_entry_taken_impl, - undo_entry_taken_ffi, - undoEntryTaken, - undo_entry_taken( - view: *mut BNBinaryView: &BinaryView, - entry: *mut BNUndoEntry: &UndoEntry, - ), - ( - &BinaryView::from_raw(view), - &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), - ), -} -RedoEntryTaken => { - RedoEntryTakenHandler, - RedoEntryTakenDummy, - redo_entry_taken_impl, - redo_entry_taken_ffi, - redoEntryTaken, - redo_entry_taken( - view: *mut BNBinaryView: &BinaryView, - entry: *mut BNUndoEntry: &UndoEntry, - ), - ( - &BinaryView::from_raw(view), - &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), + len: u64: u64 = len, + ), + functionAdded => function_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + func: *mut BNFunction: &Function = &Function::from_raw(func), + ), + functionRemoved => function_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + func: *mut BNFunction: &Function = &Function::from_raw(func), + ), + functionUpdated => function_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + func: *mut BNFunction: &Function = &Function::from_raw(func), + ), + functionUpdateRequested => function_update_requested( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + func: *mut BNFunction: &Function = &Function::from_raw(func), + ), + dataVariableAdded => data_variable_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + var: *mut BNDataVariable: &DataVariable = &DataVariable::from_raw(&*var), + ), + dataVariableRemoved => data_variable_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + var: *mut BNDataVariable: &DataVariable = &DataVariable::from_raw(&*var), + ), + dataVariableUpdated => data_variable_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + var: *mut BNDataVariable: &DataVariable = &DataVariable::from_raw(&*var), + ), + dataMetadataUpdated => data_metadata_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + offset: u64: u64 = offset, + ), + tagTypeUpdated => tag_type_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + tag_type: *mut BNTagType: &TagType = &TagType{ handle: tag_type }, + ), + tagAdded => tag_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + tag_ref: *mut BNTagReference: &TagReference = &TagReference::from(&*tag_ref), + ), + tagRemoved => tag_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + tag_ref: *mut BNTagReference: &TagReference = &TagReference::from(&*tag_ref), + ), + tagUpdated => tag_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + tag_ref: *mut BNTagReference: &TagReference = &TagReference::from(&*tag_ref), + ), + symbolAdded => symbol_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + sym: *mut BNSymbol: &Symbol = &Symbol::from_raw(sym), + ), + symbolRemoved => symbol_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + sym: *mut BNSymbol: &Symbol = &Symbol::from_raw(sym), + ), + symbolUpdated => symbol_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + sym: *mut BNSymbol: &Symbol = &Symbol::from_raw(sym), + ), + stringFound => string_found( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + type_: BNStringType: StringType = type_, + offset: u64: u64 = offset, + len: usize: usize = len, + ), + stringRemoved => string_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + type_: BNStringType: StringType = type_, + offset: u64: u64 = offset, + len: usize: usize = len, + ), + typeDefined => type_defined( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + name: *mut BNQualifiedName: &QualifiedName = &QualifiedName::from_raw(&*name), + type_: *mut BNType: &Type = &Type::from_raw(type_), + ), + typeUndefined => type_undefined( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + name: *mut BNQualifiedName: &QualifiedName = &QualifiedName::from_raw(&*name), + type_: *mut BNType: &Type = &Type::from_raw(type_), + ), + typeReferenceChanged => type_reference_changed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + name: *mut BNQualifiedName: &QualifiedName = &QualifiedName::from_raw(&*name), + type_: *mut BNType: &Type = &Type::from_raw(type_), + ), + typeFieldReferenceChanged => type_field_reference_changed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + name: *mut BNQualifiedName: &QualifiedName = &QualifiedName::from_raw(&*name), + offset: u64: u64 = offset, + ), + segmentAdded => segment_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + segment: *mut BNSegment: &Segment = &Segment::from_raw(segment), + ), + segmentRemoved => segment_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + segment: *mut BNSegment: &Segment = &Segment::from_raw(segment), + ), + segmentUpdated => segment_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + segment: *mut BNSegment: &Segment = &Segment::from_raw(segment), + ), + sectionAdded => section_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + section: *mut BNSection: &Section = &Section::from_raw(section), + ), + sectionRemoved => section_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + section: *mut BNSection: &Section = &Section::from_raw(section), + ), + sectionUpdated => section_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + section: *mut BNSection: &Section = &Section::from_raw(section), + ), + componentNameUpdated => component_name_updated( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + previous_name: *mut ::std::os::raw::c_char: &str = CStr::from_ptr(previous_name).to_str().unwrap(), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + ), + componentAdded => component_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + ), + componentMoved => component_moved( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + former_parent: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(former_parent).unwrap()), + new_parent: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(new_parent).unwrap()), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + ), + componentRemoved => component_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + former_parent: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(former_parent).unwrap()), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + ), + componentFunctionAdded => component_function_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + function: *mut BNFunction: &Function = &Function::from_raw(function), + ), + componentFunctionRemoved => component_function_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + function: *mut BNFunction: &Function = &Function::from_raw(function), + ), + componentDataVariableAdded => component_data_variable_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + var: *mut BNDataVariable: &DataVariable = &DataVariable::from_raw(&*var), + ), + componentDataVariableRemoved => component_data_variable_removed( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + component: *mut BNComponent: &Component = &Component::from_raw(ptr::NonNull::new(component).unwrap()), + var: *mut BNDataVariable: &DataVariable = &DataVariable::from_raw(&*var), + ), + externalLibraryAdded => external_library_added( + data: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(data), + library: *mut BNExternalLibrary: &ExternalLibrary = &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()), + ), + externalLibraryUpdated => external_library_updated( + data: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(data), + library: *mut BNExternalLibrary: &ExternalLibrary = &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()), + ), + externalLibraryRemoved => external_library_removed( + data: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(data), + library: *mut BNExternalLibrary: &ExternalLibrary = &ExternalLibrary::from_raw(ptr::NonNull::new(library).unwrap()), + ), + externalLocationAdded => external_location_added( + data: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(data), + location: *mut BNExternalLocation: &ExternalLocation = &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()), + ), + externalLocationUpdated => external_location_updated( + data: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(data), + location: *mut BNExternalLocation: &ExternalLocation = &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()), + ), + externalLocationRemoved => external_location_removed( + data: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(data), + location: *mut BNExternalLocation: &ExternalLocation = &ExternalLocation::from_raw(ptr::NonNull::new(location).unwrap()), + ), + typeArchiveAttached => type_archive_attached( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + id: *const ::std::os::raw::c_char: &str = CStr::from_ptr(id).to_str().unwrap(), + path: *const ::std::os::raw::c_char: &[u8] = CStr::from_ptr(path).to_bytes(), + ), + typeArchiveDetached => type_archive_detached( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + id: *const ::std::os::raw::c_char: &str = CStr::from_ptr(id).to_str().unwrap(), + path: *const ::std::os::raw::c_char: &[u8] = CStr::from_ptr(path).to_bytes(), + ), + typeArchiveConnected => type_archive_connected( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + archive: *mut BNTypeArchive: &TypeArchive = &TypeArchive::from_raw(ptr::NonNull::new(archive).unwrap()), + ), + typeArchiveDisconnected => type_archive_disconnected( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + archive: *mut BNTypeArchive: &TypeArchive = &TypeArchive::from_raw(ptr::NonNull::new(archive).unwrap()), + ), + undoEntryAdded => undo_entry_added( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + entry: *mut BNUndoEntry: &UndoEntry = &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), + ), + undoEntryTaken => undo_entry_taken( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + entry: *mut BNUndoEntry: &UndoEntry = &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), + ), + redoEntryTaken => redo_entry_taken( + view: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(view), + entry: *mut BNUndoEntry: &UndoEntry = &UndoEntry::from_raw(ptr::NonNull::new(entry).unwrap()), + ), + rebased => rebased( + oldview: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(oldview), + newview: *mut BNBinaryView: &BinaryView = &BinaryView::from_raw(newview), ), } -Rebased => { - RebasedHandler, - RebasedDummy, - rebased_impl, - rebased_ffi, - rebased, - rebased( - oldview: *mut BNBinaryView: &BinaryView, - newview: *mut BNBinaryView: &BinaryView, - ), - (&BinaryView::from_raw(oldview), &BinaryView::from_raw(newview)), -}); pub struct DataNotificationHandle<'a, T: CustomDataNotification> where diff --git a/rust/tests/data_notification.rs b/rust/tests/data_notification.rs index dd4c783a0..2ba67b7c3 100644 --- a/rust/tests/data_notification.rs +++ b/rust/tests/data_notification.rs @@ -47,77 +47,13 @@ fn test_data_notification_impl() { } impl CustomDataNotification for Tag { - // unfortunately rust is not able to fill those types automatically - // this will probably only be possible after the feature - // associated_type_defaults is merged: - // https://github.com/rust-lang/rust/issues/29661 - type NotificationBarrier = NotificationBarrierDummy; - type DataWritten = DataWrittenDummy; - type DataInserted = DataInsertedDummy; - type DataRemoved = DataRemovedDummy; - type FunctionAdded = FunctionAddedDummy; - type FunctionRemoved = FunctionRemovedDummy; - type FunctionUpdated = FunctionUpdatedDummy; - type FunctionUpdateRequested = FunctionUpdateRequestedDummy; - type DataVariableAdded = DataVariableAddedDummy; - type DataVariableRemoved = DataVariableRemovedDummy; - type DataVariableUpdated = DataVariableUpdatedDummy; - type DataMetadataUpdated = DataMetadataUpdatedDummy; - type TagTypeUpdated = TagTypeUpdatedDummy; - type TagUpdated = TagUpdatedDummy; - type TagRemoved = TagRemovedDummy; - type SymbolAdded = SymbolAddedDummy; - type SymbolRemoved = SymbolRemovedDummy; - type SymbolUpdated = SymbolUpdatedDummy; - type StringFound = StringFoundDummy; - type StringRemoved = StringRemovedDummy; - type TypeDefined = TypeDefinedDummy; - type TypeUndefined = TypeUndefinedDummy; - type TypeReferenceChanged = TypeReferenceChangedDummy; - type TypeFieldReferenceChanged = TypeFieldReferenceChangedDummy; - type SegmentAdded = SegmentAddedDummy; - type SegmentRemoved = SegmentRemovedDummy; - type SegmentUpdated = SegmentUpdatedDummy; - type SectionAdded = SectionAddedDummy; - type SectionRemoved = SectionRemovedDummy; - type SectionUpdated = SectionUpdatedDummy; - type ComponentNameUpdated = ComponentNameUpdatedDummy; - type ComponentAdded = ComponentAddedDummy; - type ComponentMoved = ComponentMovedDummy; - type ComponentRemoved = ComponentRemovedDummy; - type ComponentFunctionAdded = ComponentFunctionAddedDummy; - type ComponentFunctionRemoved = ComponentFunctionRemovedDummy; - type ComponentDataVariableAdded = ComponentDataVariableAddedDummy; - type ComponentDataVariableRemoved = ComponentDataVariableRemovedDummy; - type ExternalLibraryAdded = ExternalLibraryAddedDummy; - type ExternalLibraryUpdated = ExternalLibraryUpdatedDummy; - type ExternalLibraryRemoved = ExternalLibraryRemovedDummy; - type ExternalLocationAdded = ExternalLocationAddedDummy; - type ExternalLocationUpdated = ExternalLocationUpdatedDummy; - type ExternalLocationRemoved = ExternalLocationRemovedDummy; - type TypeArchiveAttached = TypeArchiveAttachedDummy; - type TypeArchiveDetached = TypeArchiveDetachedDummy; - type TypeArchiveConnected = TypeArchiveConnectedDummy; - type TypeArchiveDisconnected = TypeArchiveDisconnectedDummy; - type UndoEntryAdded = UndoEntryAddedDummy; - type UndoEntryTaken = UndoEntryTakenDummy; - type RedoEntryTaken = RedoEntryTakenDummy; - type Rebased = RebasedDummy; - - type TagAdded = Self; - - fn tag_added_impl(&mut self) -> Option<&mut Self> { - Some(self) - } - } - - impl TagAddedHandler for Tag { fn tag_added(&mut self, _view: &BinaryView, _tag_ref: &TagReference) { self.tags += 1; } } - let tags_lock = Tag::default().register(&bv); + let triggers = DataNotificationTriggers::default().tag_added(); + let tags_lock = Tag::default().register(&bv, triggers); let funcs = bv.functions(); for (i, func) in funcs.iter().enumerate() { From 3ab4cb096e5d821e12372763d63428ec5b3f32a0 Mon Sep 17 00:00:00 2001 From: rbran Date: Fri, 4 Apr 2025 17:48:45 +0000 Subject: [PATCH 3/4] add documentation to rust data notification --- rust/src/data_notification.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/rust/src/data_notification.rs b/rust/src/data_notification.rs index b617d380c..464e4c2a4 100644 --- a/rust/src/data_notification.rs +++ b/rust/src/data_notification.rs @@ -37,6 +37,10 @@ macro_rules! trait_handler { ) $(-> $ret_type:ty)? ),* $(,)? ) => { + /// Used to describe which call should be triggered by BinaryNinja. + /// By default all calls are disabled. + /// + /// Used by [CustomDataNotification::register] #[derive(Default)] pub struct DataNotificationTriggers { $($fun_name: bool,)* @@ -75,7 +79,7 @@ macro_rules! trait_handler { handle.$fun_name($($value_calculated),*) } )* - pub fn register_data_notification<'a, H: CustomDataNotification + 'a>( + fn register_data_notification<'a, H: CustomDataNotification + 'a>( view: &BinaryView, notify: H, triggers: DataNotificationTriggers, @@ -94,6 +98,20 @@ macro_rules! trait_handler { } } + /// Implement closures that will be called by BinaryNinja on the event of + /// data modification. + /// + /// example: + /// ```no_run + /// # use binaryninja::data_notification::DataNotificationClosure; + /// # use binaryninja::function::Function; + /// # use binaryninja::binary_view::BinaryView; + /// # let bv: BinaryView = todo!(); + /// let custom = DataNotificationClosure::default() + /// .function_updated(|_bv: &BinaryView, _func: &Function| todo!() ) + /// // other calls should be added here + /// .register(&bv); + /// ``` pub struct DataNotificationClosure<'a> { $( $fun_name: Option Date: Mon, 5 May 2025 11:52:14 +0000 Subject: [PATCH 4/4] remove the use of Box in data_notification --- rust/src/data_notification.rs | 54 +++++++++++---------------------- rust/tests/data_notification.rs | 16 +++++----- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/rust/src/data_notification.rs b/rust/src/data_notification.rs index 464e4c2a4..073c8eec4 100644 --- a/rust/src/data_notification.rs +++ b/rust/src/data_notification.rs @@ -1,4 +1,5 @@ use core::ffi; +use core::pin::Pin; use core::ptr; use std::ffi::CStr; @@ -40,7 +41,7 @@ macro_rules! trait_handler { /// Used to describe which call should be triggered by BinaryNinja. /// By default all calls are disabled. /// - /// Used by [CustomDataNotification::register] + /// Used by [CustomDataNotification::register] and [register_data_notification]. #[derive(Default)] pub struct DataNotificationTriggers { $($fun_name: bool,)* @@ -62,12 +63,16 @@ macro_rules! trait_handler { } )* + /// Register the data notification functions. + /// + /// If the type don't implement Unpin, use the function + /// [register_data_notification] with the pinned value. fn register<'a>( - self, + &'a mut self, view: &BinaryView, triggers: DataNotificationTriggers, - ) -> DataNotificationHandle<'a, Self> where Self: 'a + Sized { - register_data_notification(view, self, triggers) + ) -> DataNotificationHandle<'a, Self> where Self: 'a + Sized + Unpin { + register_data_notification(view, Pin::new(self), triggers) } } $( @@ -79,15 +84,14 @@ macro_rules! trait_handler { handle.$fun_name($($value_calculated),*) } )* - fn register_data_notification<'a, H: CustomDataNotification + 'a>( + pub fn register_data_notification<'a, H: 'a + CustomDataNotification>( view: &BinaryView, - notify: H, + notify: Pin<&'a H>, triggers: DataNotificationTriggers, ) -> DataNotificationHandle<'a, H> { - // SAFETY: this leak is undone on drop - let leak_notify = Box::leak(Box::new(notify)); + let notify = unsafe { Pin::into_inner_unchecked(notify) as *const H }; let mut handle = BNBinaryDataNotification { - context: leak_notify as *mut _ as *mut ffi::c_void, + context: notify as *const ffi::c_void as *mut ffi::c_void, $($ffi_param_name: triggers.$fun_name.then_some($fun_name::)),* }; unsafe { BNRegisterDataNotification(view.handle, &mut handle) }; @@ -140,7 +144,7 @@ macro_rules! trait_handler { )* pub fn register( - self, + &'a self, view: &BinaryView, ) -> DataNotificationHandle<'a, Self> { let mut triggers = DataNotificationTriggers::default(); @@ -149,7 +153,7 @@ macro_rules! trait_handler { triggers = triggers.$fun_name(); } )* - register_data_notification(view, self, triggers) + register_data_notification(view, Pin::new(self), triggers) } } @@ -402,36 +406,14 @@ trait_handler! { ), } -pub struct DataNotificationHandle<'a, T: CustomDataNotification> -where - T: 'a, -{ +pub struct DataNotificationHandle<'a, T> { bv: Ref, handle: BNBinaryDataNotification, _life: std::marker::PhantomData<&'a T>, } -impl DataNotificationHandle<'_, T> { - unsafe fn unregister_bv(&mut self) { - BNUnregisterDataNotification(self.bv.handle, &mut self.handle) - } - - unsafe fn extract_context(&mut self) -> Box { - Box::from_raw(self.handle.context as *mut T) - } - - pub fn unregister(self) -> T { - // NOTE don't drop the ctxt, return it - let mut slf = core::mem::ManuallyDrop::new(self); - unsafe { slf.unregister_bv() }; - unsafe { *slf.extract_context() } - } -} - -impl Drop for DataNotificationHandle<'_, T> { +impl<'a, T> Drop for DataNotificationHandle<'a, T> { fn drop(&mut self) { - unsafe { self.unregister_bv() }; - // drop context, avoid memory leak - let _ctxt = unsafe { self.extract_context() }; + unsafe { BNUnregisterDataNotification(self.bv.handle, &mut self.handle) } } } diff --git a/rust/tests/data_notification.rs b/rust/tests/data_notification.rs index 2ba67b7c3..06b88da88 100644 --- a/rust/tests/data_notification.rs +++ b/rust/tests/data_notification.rs @@ -13,11 +13,12 @@ fn test_data_notification_dyn_closure() { let bv = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view"); let mut func_updated_count = 0usize; - let custom = DataNotificationClosure::default() - .function_updated(|_bv: &BinaryView, _func: &Function| { + let custom = DataNotificationClosure::default().function_updated( + |_bv: &BinaryView, _func: &Function| { func_updated_count += 1; - }) - .register(&bv); + }, + ); + custom.register(&bv); let funcs = bv.functions(); for func in &funcs { @@ -30,7 +31,7 @@ fn test_data_notification_dyn_closure() { None, ); } - custom.unregister(); + drop(custom); assert_eq!(funcs.len(), func_updated_count); } @@ -53,7 +54,8 @@ fn test_data_notification_impl() { } let triggers = DataNotificationTriggers::default().tag_added(); - let tags_lock = Tag::default().register(&bv, triggers); + let mut tags = Tag::default(); + let tags_lock = tags.register(&bv, triggers); let funcs = bv.functions(); for (i, func) in funcs.iter().enumerate() { @@ -61,7 +63,7 @@ fn test_data_notification_impl() { func.add_tag(&crash, "Dummy tag", Some(i.try_into().unwrap()), true, None); } - let tags = tags_lock.unregister(); + drop(tags_lock); assert_eq!(funcs.len(), tags.tags); }