diff options
| author | Mason Reed <mason@vector35.com> | 2026-03-13 12:24:18 -0700 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2026-03-24 18:46:48 -0700 |
| commit | 3c88b11e5df33116580ac008e36092775df66135 (patch) | |
| tree | cd64fbe149f05683ddabcccd0db7b87356f1f8cf /plugins/warp/src/plugin/ffi/processor.rs | |
| parent | f325aa7b6026a1daef84931baeb1f50d7da10c10 (diff) | |
[WARP] Improved UX and API
- Exposes WARP type objects directly
- Adds processor API (for generating warp files directly)
- Adds file and chunk API
- Misc cleanup
- Simplified the amount of commands
- Replaced the "Create" commands with a purpose built processor dialog
- Added a native QT viewer for WARP files
- Simplified committing to a remote with a purpose built commit dialog
Diffstat (limited to 'plugins/warp/src/plugin/ffi/processor.rs')
| -rw-r--r-- | plugins/warp/src/plugin/ffi/processor.rs | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/plugins/warp/src/plugin/ffi/processor.rs b/plugins/warp/src/plugin/ffi/processor.rs new file mode 100644 index 00000000..83b47f5a --- /dev/null +++ b/plugins/warp/src/plugin/ffi/processor.rs @@ -0,0 +1,187 @@ +use crate::plugin::ffi::file::{BNWARPFile, RcWarpFile}; +use crate::processor::{ + IncludedDataField, IncludedFunctionsField, ProcessingFileState, WarpFileProcessor, + WarpFileProcessorEntry, +}; +use binaryninja::binary_view::BinaryView; +use binaryninja::project::file::ProjectFile; +use binaryninja::project::Project; +use binaryninjacore_sys::{BNBinaryView, BNProject, BNProjectFile}; +use std::ffi::{c_char, CStr, CString}; +use std::mem::ManuallyDrop; +use std::path::PathBuf; +use std::ptr::NonNull; +use std::sync::Arc; +use warp::chunk::CompressionType; + +pub type BNWARPProcessor = WarpFileProcessor; + +#[repr(C)] +pub struct BNWARPProcessorState { + cancelled: bool, + unprocessed_files_count: usize, + processed_files_count: usize, + analyzing_files: *mut *mut c_char, + analyzing_files_count: usize, + processing_files: *mut *mut c_char, + processing_files_count: usize, +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPNewProcessor( + included_data: IncludedDataField, + included_functions: IncludedFunctionsField, + worker_count: usize, +) -> *mut BNWARPProcessor { + let processor = WarpFileProcessor::new() + .with_file_data(included_data) + .with_included_functions(included_functions) + .with_compression_type(CompressionType::Zstd) + .with_entry_worker_count(worker_count); + Box::into_raw(Box::new(processor)) +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorAddPath( + processor: *mut BNWARPProcessor, + path: *const c_char, +) { + let mut processor = ManuallyDrop::new(Box::from_raw(processor)); + let path_cstr = unsafe { CStr::from_ptr(path) }; + let path = PathBuf::from(path_cstr.to_str().unwrap()); + // TODO: Not thread safe. + processor.add_entry(WarpFileProcessorEntry::Path(path)); +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorAddProject( + processor: *mut BNWARPProcessor, + project: *mut BNProject, +) { + let mut processor = ManuallyDrop::new(Box::from_raw(processor)); + let project = Project::from_raw(NonNull::new(project).unwrap()); + // TODO: Not thread safe. + processor.add_entry(WarpFileProcessorEntry::Project(project.to_owned())); +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorAddProjectFile( + processor: *mut BNWARPProcessor, + project_file: *mut BNProjectFile, +) { + let mut processor = ManuallyDrop::new(Box::from_raw(processor)); + let project_file = ProjectFile::from_raw(NonNull::new(project_file).unwrap()); + // TODO: Not thread safe. + processor.add_entry(WarpFileProcessorEntry::ProjectFile(project_file.to_owned())); +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorAddBinaryView( + processor: *mut BNWARPProcessor, + view: *mut BNBinaryView, +) { + let mut processor = ManuallyDrop::new(Box::from_raw(processor)); + let view = BinaryView::from_raw(view); + // TODO: Not thread safe. + processor.add_entry(WarpFileProcessorEntry::BinaryView(view.to_owned())); +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorStart(processor: *mut BNWARPProcessor) -> *mut BNWARPFile { + let mut processor = ManuallyDrop::new(Box::from_raw(processor)); + // TODO: Not thread safe. + match processor.process_entries() { + Ok(file) => { + let rc_file = RcWarpFile::from(file); + Arc::into_raw(Arc::new(rc_file)) as *mut BNWARPFile + } + Err(_) => std::ptr::null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorIsCancelled(processor: *mut BNWARPProcessor) -> bool { + let processor = ManuallyDrop::new(Box::from_raw(processor)); + processor + .state() + .cancelled + .load(std::sync::atomic::Ordering::Relaxed) +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorCancel(processor: *mut BNWARPProcessor) { + let processor = ManuallyDrop::new(Box::from_raw(processor)); + processor + .state() + .cancelled + .store(true, std::sync::atomic::Ordering::Relaxed) +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPProcessorGetState( + processor: *mut BNWARPProcessor, +) -> BNWARPProcessorState { + let processor = ManuallyDrop::new(Box::from_raw(processor)); + let processor_state = processor.state(); + + let mut unprocessed_files_count = 0; + let mut processed_files_count = 0; + let mut analyzing_files = Vec::new(); + let mut processing_files = Vec::new(); + + for file_state in &processor_state.files { + match file_state.value() { + ProcessingFileState::Unprocessed => unprocessed_files_count += 1, + ProcessingFileState::Analyzing => analyzing_files.push(file_state.key().clone()), + ProcessingFileState::Processing => processing_files.push(file_state.key().clone()), + ProcessingFileState::Processed => processed_files_count += 1, + } + } + + let raw_analyzing_files: Box<[_]> = analyzing_files + .into_iter() + .map(|p| CString::new(p.to_str().unwrap()).unwrap().into_raw()) + .collect(); + let raw_analyzing_files_count = raw_analyzing_files.len(); + let raw_analyzing_files_ptr = Box::into_raw(raw_analyzing_files); + + let raw_processing_files: Box<[_]> = processing_files + .into_iter() + .map(|p| CString::new(p.to_str().unwrap()).unwrap().into_raw()) + .collect(); + let raw_processing_files_count = raw_processing_files.len(); + let raw_processing_files_ptr = Box::into_raw(raw_processing_files); + + BNWARPProcessorState { + cancelled: processor_state + .cancelled + .load(std::sync::atomic::Ordering::Relaxed), + unprocessed_files_count, + processed_files_count, + analyzing_files: raw_analyzing_files_ptr as *mut *mut c_char, + analyzing_files_count: raw_analyzing_files_count, + processing_files: raw_processing_files_ptr as *mut *mut c_char, + processing_files_count: raw_processing_files_count, + } +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFreeProcessor(processor: *mut BNWARPProcessor) { + let _ = Box::from_raw(processor); +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFreeProcessorState(state: BNWARPProcessorState) { + let a_files_ptr = + std::ptr::slice_from_raw_parts_mut(state.analyzing_files, state.analyzing_files_count); + let a_files_boxed = unsafe { Box::from_raw(a_files_ptr) }; + for path in a_files_boxed.iter() { + let _ = CString::from_raw(*path); + } + let p_files_ptr = + std::ptr::slice_from_raw_parts_mut(state.processing_files, state.processing_files_count); + let p_files_boxed = unsafe { Box::from_raw(p_files_ptr) }; + for path in p_files_boxed.iter() { + let _ = CString::from_raw(*path); + } +} |
