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 | |
| 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')
| -rw-r--r-- | plugins/warp/src/plugin/ffi/container.rs | 61 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/ffi/file.rs | 137 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/ffi/function.rs | 19 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/ffi/processor.rs | 187 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/ffi/ty.rs | 75 |
5 files changed, 422 insertions, 57 deletions
diff --git a/plugins/warp/src/plugin/ffi/container.rs b/plugins/warp/src/plugin/ffi/container.rs index aa0c37d3..09f15d99 100644 --- a/plugins/warp/src/plugin/ffi/container.rs +++ b/plugins/warp/src/plugin/ffi/container.rs @@ -3,17 +3,11 @@ use crate::container::disk::DiskContainer; use crate::container::{ ContainerSearchItem, ContainerSearchItemKind, ContainerSearchQuery, SourcePath, SourceTag, }; -use crate::convert::{from_bn_type, to_bn_type}; use crate::plugin::ffi::{ BNWARPConstraintGUID, BNWARPContainer, BNWARPFunction, BNWARPFunctionGUID, BNWARPSource, - BNWARPTarget, BNWARPTypeGUID, + BNWARPTarget, BNWARPType, BNWARPTypeGUID, }; -use binaryninja::architecture::CoreArchitecture; -use binaryninja::binary_view::BinaryView; -use binaryninja::rc::Ref; use binaryninja::string::BnString; -use binaryninja::types::Type; -use binaryninjacore_sys::{BNArchitecture, BNBinaryView, BNType}; use std::collections::HashMap; use std::ffi::{c_char, CStr}; use std::mem::ManuallyDrop; @@ -98,32 +92,25 @@ pub unsafe extern "C" fn BNWARPContainerSearchItemGetSource( #[no_mangle] pub unsafe extern "C" fn BNWARPContainerSearchItemGetType( - arch: *mut BNArchitecture, item: *mut BNWARPContainerSearchItem, -) -> *mut BNType { - // NOTE: to convert the type, we must have an architecture. - let arch = match !arch.is_null() { - true => Some(CoreArchitecture::from_raw(arch)), - false => None, - }; - +) -> *mut BNWARPType { let item = ManuallyDrop::new(Arc::from_raw(item)); match &item.kind { ContainerSearchItemKind::Source { .. } => std::ptr::null_mut(), ContainerSearchItemKind::Function(func) => { match &func.ty { None => std::ptr::null_mut(), - Some(ty) => { - let bn_ty = to_bn_type(arch, &ty); - // NOTE: The type ref has been pre-incremented for the caller. - unsafe { Ref::into_raw(bn_ty) }.handle + Some(func_ty) => { + let arc_func_ty = Arc::new(func_ty.clone()); + // NOTE: Freed by BNWARPFreeTypeReference + Arc::into_raw(arc_func_ty) as *mut BNWARPType } } } ContainerSearchItemKind::Type(ty) => { - let bn_ty = to_bn_type(arch, &ty); - // NOTE: The type ref has been pre-incremented for the caller. - unsafe { Ref::into_raw(bn_ty) }.handle + let arc_ty = Arc::new(ty.clone()); + // NOTE: Freed by BNWARPFreeTypeReference + Arc::into_raw(arc_ty) as *mut BNWARPType } ContainerSearchItemKind::Symbol(_) => std::ptr::null_mut(), } @@ -254,7 +241,7 @@ pub unsafe extern "C" fn BNWARPContainerGetSources( return std::ptr::null_mut(); }; - // NOTE: Leak the sources to be freed by BNWARPFreeSourceList + // NOTE: Leak the sources to be freed by BNWARPFreeUUIDList let boxed_sources: Box<[_]> = container.sources().unwrap_or_default().into_boxed_slice(); *count = boxed_sources.len(); Box::into_raw(boxed_sources) as *mut BNWARPSource @@ -389,14 +376,11 @@ pub unsafe extern "C" fn BNWARPContainerAddFunctions( #[no_mangle] pub unsafe extern "C" fn BNWARPContainerAddTypes( - view: *mut BNBinaryView, container: *mut BNWARPContainer, source: *const BNWARPSource, - types: *mut *mut BNType, + types: *mut *mut BNWARPType, count: usize, ) -> bool { - let view = unsafe { BinaryView::from_raw(view) }; - let arc_container = ManuallyDrop::new(Arc::from_raw(container)); let Ok(mut container) = arc_container.write() else { return false; @@ -405,10 +389,11 @@ pub unsafe extern "C" fn BNWARPContainerAddTypes( let source = unsafe { *source }; let types_ptr = std::slice::from_raw_parts(types, count); + // TODO: We have to clone the objects here to make the type checker happy. + // TODO: See about avoiding this later. let types: Vec<_> = types_ptr .iter() - .map(|&t| Type::from_raw(t)) - .map(|ty| from_bn_type(&view, &ty, 255)) + .map(|&t| unsafe { ManuallyDrop::new(Arc::from_raw(t)).as_ref().clone() }) .collect(); container.add_types(&source, &types).is_ok() } @@ -476,7 +461,7 @@ pub unsafe extern "C" fn BNWARPContainerGetSourcesWithFunctionGUID( let guid = unsafe { *guid }; - // NOTE: Leak the sources to be freed by BNWARPFreeSourceList + // NOTE: Leak the sources to be freed by BNWARPFreeUUIDList let boxed_sources: Box<[_]> = container .sources_with_function_guid(&target, &guid) .unwrap_or_default() @@ -498,7 +483,7 @@ pub unsafe extern "C" fn BNWARPContainerGetSourcesWithTypeGUID( let guid = unsafe { *guid }; - // NOTE: Leak the sources to be freed by BNWARPFreeSourceList + // NOTE: Leak the sources to be freed by BNWARPFreeUUIDList let boxed_sources: Box<[_]> = container .sources_with_type_guid(&guid) .unwrap_or_default() @@ -538,22 +523,17 @@ pub unsafe extern "C" fn BNWARPContainerGetFunctionsWithGUID( Box::into_raw(raw_boxed_functions) as *mut *mut BNWARPFunction } -// TODO: Swap arch to Target? #[no_mangle] pub unsafe extern "C" fn BNWARPContainerGetTypeWithGUID( - arch: *mut BNArchitecture, container: *mut BNWARPContainer, source: *const BNWARPSource, guid: *const BNWARPTypeGUID, -) -> *mut BNType { +) -> *mut BNWARPType { let arc_container = ManuallyDrop::new(Arc::from_raw(container)); let Ok(container) = arc_container.read() else { return std::ptr::null_mut(); }; - // NOTE: to convert the type, we must have an architecture. - let arch = CoreArchitecture::from_raw(arch); - let source = unsafe { *source }; let guid = unsafe { *guid }; @@ -561,9 +541,10 @@ pub unsafe extern "C" fn BNWARPContainerGetTypeWithGUID( let Some(ty) = container.type_with_guid(&source, &guid).unwrap_or_default() else { return std::ptr::null_mut(); }; - let function_type = to_bn_type(Some(arch), &ty); - // NOTE: The type ref has been pre-incremented for the caller. - unsafe { Ref::into_raw(function_type) }.handle + + let arc_ty = Arc::new(ty); + // NOTE: Freed by BNWARPFreeTypeReference + Arc::into_raw(arc_ty) as *mut BNWARPType } #[no_mangle] diff --git a/plugins/warp/src/plugin/ffi/file.rs b/plugins/warp/src/plugin/ffi/file.rs index 951b5eb2..3abfe5aa 100644 --- a/plugins/warp/src/plugin/ffi/file.rs +++ b/plugins/warp/src/plugin/ffi/file.rs @@ -1,11 +1,43 @@ +use crate::plugin::ffi::{BNWARPFunction, BNWARPTarget, BNWARPType}; +use binaryninja::data_buffer::DataBuffer; +use binaryninjacore_sys::BNDataBuffer; use std::ffi::c_char; +use std::mem::ManuallyDrop; use std::sync::Arc; -use warp::WarpFile; +use warp::chunk::ChunkKind; +use warp::{WarpFile, WarpFileHeader}; -pub type BNWARPFile = WarpFile<'static>; +/// A [`WarpFile`] wrapper that uses reference counting to manage its chunks lifetime. +/// +/// Used primarily when passing to the C FFI so that chunks do not need to have a complicated lifetime. +pub struct RcWarpFile { + pub header: WarpFileHeader, + pub chunks: Vec<Arc<warp::chunk::Chunk<'static>>>, +} + +impl From<WarpFile<'static>> for RcWarpFile { + fn from(file: WarpFile<'static>) -> Self { + let chunks = file.chunks.into_iter().map(|c| Arc::new(c)).collect(); + Self { + header: file.header, + chunks, + } + } +} + +impl From<&RcWarpFile> for WarpFile<'static> { + fn from(rc_file: &RcWarpFile) -> Self { + let chunks = rc_file.chunks.iter().map(|c| (**c).clone()).collect(); + Self { + header: rc_file.header.clone(), + chunks, + } + } +} + +pub type BNWARPFile = RcWarpFile; -// TODO: At some point we may want to expose chunks directly. For now we will just enumerate all of them. -// pub type BNWARPChunk = warp::chunk::Chunk<'static>; +pub type BNWARPChunk = warp::chunk::Chunk<'static>; // TODO: From bytes as well. #[no_mangle] @@ -20,7 +52,78 @@ pub unsafe extern "C" fn BNWARPNewFileFromPath(path: *mut c_char) -> *mut BNWARP let Some(file) = WarpFile::from_owned_bytes(bytes) else { return std::ptr::null_mut(); }; - Arc::into_raw(Arc::new(file)) as *mut BNWARPFile + let rc_file = RcWarpFile::from(file); + Arc::into_raw(Arc::new(rc_file)) as *mut BNWARPFile +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFileGetChunks( + file: *mut BNWARPFile, + count: *mut usize, +) -> *mut *mut BNWARPChunk { + let arc_file = ManuallyDrop::new(Arc::from_raw(file)); + *count = arc_file.chunks.len(); + let boxed_chunks: Box<[_]> = arc_file + .chunks + .iter() + .map(|c| Arc::into_raw(c.clone())) + .collect(); + Box::into_raw(boxed_chunks) as *mut *mut BNWARPChunk +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFileToDataBuffer(file: *mut BNWARPFile) -> *mut BNDataBuffer { + let arc_file = ManuallyDrop::new(Arc::from_raw(file)); + let warp_file = WarpFile::from(arc_file.as_ref()); + let buffer = DataBuffer::new(&warp_file.to_bytes()); + buffer.into_raw() +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPChunkGetTarget(chunk: *const BNWARPChunk) -> *mut BNWARPTarget { + let chunk = unsafe { &*chunk }; + let chunk_target = chunk.header.target.clone(); + Arc::into_raw(Arc::new(chunk_target)) as *mut BNWARPTarget +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPChunkGetFunctions( + chunk: *const BNWARPChunk, + count: *mut usize, +) -> *mut *mut BNWARPFunction { + let chunk = unsafe { &*chunk }; + match &chunk.kind { + ChunkKind::Signature(sc) => { + let boxed_funcs: Box<[_]> = sc + .functions() + .into_iter() + .map(|f| Arc::into_raw(Arc::new(f.clone()))) + .collect(); + *count = boxed_funcs.len(); + Box::into_raw(boxed_funcs) as *mut *mut BNWARPFunction + } + ChunkKind::Type(_) => std::ptr::null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPChunkGetTypes( + chunk: *const BNWARPChunk, + count: *mut usize, +) -> *mut *mut BNWARPType { + let chunk = unsafe { &*chunk }; + match &chunk.kind { + ChunkKind::Signature(_) => std::ptr::null_mut(), + ChunkKind::Type(tc) => { + let boxed_types: Box<[_]> = tc + .types() + .into_iter() + .map(|t| Arc::into_raw(Arc::new(t.ty.clone()))) + .collect(); + *count = boxed_types.len(); + Box::into_raw(boxed_types) as *mut *mut BNWARPType + } + } } #[no_mangle] @@ -36,3 +139,27 @@ pub unsafe extern "C" fn BNWARPFreeFileReference(file: *mut BNWARPFile) { } Arc::decrement_strong_count(file); } + +#[no_mangle] +pub unsafe extern "C" fn BNWARPNewChunkReference(chunk: *mut BNWARPChunk) -> *mut BNWARPChunk { + Arc::increment_strong_count(chunk); + chunk +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFreeChunkReference(chunk: *mut BNWARPChunk) { + if chunk.is_null() { + return; + } + Arc::decrement_strong_count(chunk); +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFreeChunkList(chunks: *mut *mut BNWARPChunk, count: usize) { + let chunks_ptr = std::ptr::slice_from_raw_parts_mut(chunks, count); + let chunks = unsafe { Box::from_raw(chunks_ptr) }; + for chunk in chunks { + // NOTE: The chunks themselves should also be arc. + BNWARPFreeChunkReference(chunk); + } +} diff --git a/plugins/warp/src/plugin/ffi/function.rs b/plugins/warp/src/plugin/ffi/function.rs index 138c0a7b..2eff9e4a 100644 --- a/plugins/warp/src/plugin/ffi/function.rs +++ b/plugins/warp/src/plugin/ffi/function.rs @@ -1,11 +1,11 @@ use crate::build_function; use crate::cache::{insert_cached_function_match, try_cached_function_match}; -use crate::convert::{to_bn_symbol_at_address, to_bn_type}; -use crate::plugin::ffi::{BNWARPConstraint, BNWARPFunction, BNWARPFunctionGUID}; +use crate::convert::to_bn_symbol_at_address; +use crate::plugin::ffi::{BNWARPConstraint, BNWARPFunction, BNWARPFunctionGUID, BNWARPType}; use binaryninja::function::Function; use binaryninja::rc::Ref; use binaryninja::string::BnString; -use binaryninjacore_sys::{BNFunction, BNSymbol, BNType}; +use binaryninjacore_sys::{BNFunction, BNSymbol}; use std::ffi::c_char; use std::mem::ManuallyDrop; use std::sync::Arc; @@ -111,19 +111,14 @@ pub unsafe extern "C" fn BNWARPFunctionGetSymbolName(function: *mut BNWARPFuncti } #[no_mangle] -pub unsafe extern "C" fn BNWARPFunctionGetType( - function: *mut BNWARPFunction, - analysis_function: *mut BNFunction, -) -> *mut BNType { - let analysis_function = Function::from_raw(analysis_function); +pub unsafe extern "C" fn BNWARPFunctionGetType(function: *mut BNWARPFunction) -> *mut BNWARPType { // We do not own function so we should not drop. let function = ManuallyDrop::new(Arc::from_raw(function)); match &function.ty { Some(func_ty) => { - let arch = analysis_function.arch(); - let function_type = to_bn_type(Some(arch), func_ty); - // NOTE: The type ref has been pre-incremented for the caller. - unsafe { Ref::into_raw(function_type) }.handle + let arc_func_ty = Arc::new(func_ty.clone()); + // NOTE: Freed by BNWARPFreeTypeReference + Arc::into_raw(arc_func_ty) as *mut BNWARPType } None => std::ptr::null_mut(), } 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); + } +} diff --git a/plugins/warp/src/plugin/ffi/ty.rs b/plugins/warp/src/plugin/ffi/ty.rs new file mode 100644 index 00000000..6a16fdab --- /dev/null +++ b/plugins/warp/src/plugin/ffi/ty.rs @@ -0,0 +1,75 @@ +use crate::convert::{from_bn_type, to_bn_type}; +use crate::plugin::ffi::BNWARPType; +use binaryninja::architecture::CoreArchitecture; +use binaryninja::binary_view::BinaryView; +use binaryninja::file_metadata::FileMetadata; +use binaryninja::rc::Ref as BnRef; +use binaryninja::string::BnString; +use binaryninja::types::Type; +use binaryninjacore_sys::{BNArchitecture, BNType}; +use std::ffi::c_char; +use std::mem::ManuallyDrop; +use std::sync::Arc; + +#[no_mangle] +pub unsafe extern "C" fn BNWARPGetType( + analysis_type: *mut BNType, + confidence: u8, +) -> *mut BNWARPType { + let analysis_type = Type::from_raw(analysis_type); + // TODO: This will leak a bunch of memory, but we need to remove the view requirement anyways. + let binary_view = BinaryView::from_data(&FileMetadata::new(), &[]); + let ty = from_bn_type(&binary_view, &analysis_type, confidence); + Arc::into_raw(Arc::new(ty)) as *mut BNWARPType +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPTypeGetName(ty: *mut BNWARPType) -> *mut c_char { + let ty = ManuallyDrop::new(Arc::from_raw(ty)); + match ty.name.as_deref() { + Some(name) => BnString::into_raw(BnString::new(name)), + None => std::ptr::null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPTypeGetConfidence(ty: *mut BNWARPType) -> u8 { + let ty = ManuallyDrop::new(Arc::from_raw(ty)); + ty.confidence +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPTypeGetAnalysisType( + arch: *mut BNArchitecture, + ty: *mut BNWARPType, +) -> *mut BNType { + let ty = ManuallyDrop::new(Arc::from_raw(ty)); + let analysis_ty = match arch.is_null() { + true => to_bn_type::<CoreArchitecture>(None, &ty), + false => to_bn_type(Some(CoreArchitecture::from_raw(arch)), &ty), + }; + BnRef::into_raw(analysis_ty).handle +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPNewTypeReference(ty: *mut BNWARPType) -> *mut BNWARPType { + Arc::increment_strong_count(ty); + ty +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFreeTypeReference(ty: *mut BNWARPType) { + if ty.is_null() { + return; + } + Arc::decrement_strong_count(ty); +} + +#[no_mangle] +pub unsafe extern "C" fn BNWARPFreeTypeList(types: *mut *mut BNWARPType, count: usize) { + let types_ptr = std::ptr::slice_from_raw_parts_mut(types, count); + let types = unsafe { Box::from_raw(types_ptr) }; + for ty in types { + unsafe { BNWARPFreeTypeReference(ty) }; + } +} |
