Skip to content

Commit

Permalink
Rust: remove direct dependency on the libc crate
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrasnitski committed Jul 17, 2024
1 parent ab5c0b3 commit 35d8650
Show file tree
Hide file tree
Showing 25 changed files with 180 additions and 205 deletions.
1 change: 0 additions & 1 deletion rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ noexports = []
[dependencies]
lazy_static = "1.4.0"
log = "0.4"
libc = "0.2"
rayon = { version = "1.8", optional = true }
binaryninjacore-sys = { path = "binaryninjacore-sys" }

Expand Down
76 changes: 55 additions & 21 deletions rust/src/architecture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use binaryninjacore_sys::*;

use std::{
alloc,
borrow::{Borrow, Cow},
collections::HashMap,
ffi::{c_char, c_int, CStr, CString},
Expand Down Expand Up @@ -1696,8 +1697,8 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync + Sized,
F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
{
use std::ffi::{c_char, c_void};
use std::mem;
use std::os::raw::{c_char, c_void};

#[repr(C)]
struct ArchitectureBuilder<A, F>
Expand Down Expand Up @@ -2096,30 +2097,44 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };

if let Some(group) = custom_arch.flag_group_from_id(group) {
let flag_conditions = group.flag_conditions();
let Some(group) = custom_arch.flag_group_from_id(group) else {
unsafe { *count = 0 };
return ptr::null_mut();
};

unsafe {
let allocation_size =
mem::size_of::<BNFlagConditionForSemanticClass>() * flag_conditions.len();
let result = libc::malloc(allocation_size) as *mut BNFlagConditionForSemanticClass;
let out_slice = slice::from_raw_parts_mut(result, flag_conditions.len());
let flag_conditions = group.flag_conditions();

for (i, (class, cond)) in flag_conditions.iter().enumerate() {
let out = out_slice.get_unchecked_mut(i);
let conds: Box<[_]> = flag_conditions
.iter()
.map(|(class, cond)| BNFlagConditionForSemanticClass {
semanticClass: class.id(),
condition: *cond,
})
.collect();

out.semanticClass = class.id();
out.condition = *cond;
}
// Extremely gross. We want to smuggle the length through FFI so that we can free the array
// later, so we construct a custom Layout containing one `usize` followed by all the
// conditions, then allocate according to this layout.
let len = flag_conditions.len();
let (layout, offset) = alloc::Layout::new::<usize>()
.extend(alloc::Layout::array::<BNFlagConditionForSemanticClass>(len).unwrap())
.map(|(layout, offset)| (layout.pad_to_align(), offset))
.unwrap();

*count = flag_conditions.len();
result
}
} else {
unsafe {
*count = 0;
unsafe {
let raw: *mut u8 = alloc::alloc(layout);
if raw.is_null() {
return ptr::null_mut();
}
ptr::null_mut()

// Smuggle the length
raw.cast::<usize>().write(len);
// Offset past the length, now we're just pointing at the conditions
let raw = raw.add(offset).cast::<BNFlagConditionForSemanticClass>();
raw.copy_from(conds.as_ptr(), len);

count.write(len);
raw
}
}

Expand All @@ -2129,8 +2144,27 @@ where
) where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
if conds.is_null() {
return;
}

// We don't know the length yet, and the alignment of an array is the same as its elements,
// so we just mock [T; N] with T in order to obtain the offset we want.
let offset = alloc::Layout::new::<usize>()
.extend(alloc::Layout::new::<BNFlagConditionForSemanticClass>())
.unwrap()
.1;

unsafe {
libc::free(conds as *mut _);
// Read out the smuggled length, then recalculate the *actual* layout of the data given
// the length, and finally free the memory.
let base = conds.cast::<u8>().sub(offset);
let len = base.cast::<usize>().read();
let layout = alloc::Layout::new::<usize>()
.extend(alloc::Layout::array::<BNFlagConditionForSemanticClass>(len).unwrap())
.unwrap()
.0;
alloc::dealloc(base, layout);
}
}

Expand Down
21 changes: 5 additions & 16 deletions rust/src/binaryview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,15 +268,11 @@ pub trait BinaryViewExt: BinaryViewBase {
}

fn original_base(&self) -> u64 {
unsafe {
BNGetOriginalBase(self.as_ref().handle)
}
unsafe { BNGetOriginalBase(self.as_ref().handle) }
}

fn set_original_base(&self, base: u64) {
unsafe {
BNSetOriginalBase(self.as_ref().handle, base)
}
unsafe { BNSetOriginalBase(self.as_ref().handle, base) }
}

fn end(&self) -> u64 {
Expand Down Expand Up @@ -1411,10 +1407,7 @@ pub trait BinaryViewExt: BinaryViewBase {
unsafe { BNRemoveComponentByGuid(self.as_ref().handle, path.as_ptr()) }
}

fn data_variable_parent_components(
&self,
data_variable: &DataVariable,
) -> Array<Component> {
fn data_variable_parent_components(&self, data_variable: &DataVariable) -> Array<Component> {
let mut count = 0;
let result = unsafe {
BNGetDataVariableParentComponents(
Expand Down Expand Up @@ -1835,7 +1828,7 @@ where
Handler: BinaryViewEventHandler,
{
unsafe extern "C" fn on_event<Handler: BinaryViewEventHandler>(
ctx: *mut ::std::os::raw::c_void,
ctx: *mut c_void,
view: *mut BNBinaryView,
) {
ffi_wrap!("EventHandler::on_event", {
Expand All @@ -1848,10 +1841,6 @@ where
let raw = Box::into_raw(boxed);

unsafe {
BNRegisterBinaryViewEvent(
event_type,
Some(on_event::<Handler>),
raw as *mut ::std::os::raw::c_void,
);
BNRegisterBinaryViewEvent(event_type, Some(on_event::<Handler>), raw as *mut c_void);
}
}
6 changes: 2 additions & 4 deletions rust/src/callingconvention.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,17 @@
//! Contains and provides information about different systems' calling conventions to analysis.
use std::borrow::Borrow;
use std::ffi::c_void;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use std::mem;
use std::os::raw::c_void;
use std::ptr;
use std::slice;

use binaryninjacore_sys::*;

use crate::architecture::{Architecture, ArchitectureExt, CoreArchitecture, Register};
use crate::rc::{
CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable,
};
use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
use crate::string::*;

// TODO
Expand Down
2 changes: 1 addition & 1 deletion rust/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use binaryninjacore_sys::{
BNRegisterPluginCommandForFunction, BNRegisterPluginCommandForRange,
};

use std::ffi::c_void;
use std::ops::Range;
use std::os::raw::c_void;

use crate::binaryview::BinaryView;
use crate::function::Function;
Expand Down
2 changes: 1 addition & 1 deletion rust/src/custombinaryview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use binaryninjacore_sys::*;

pub use binaryninjacore_sys::BNModificationStatus as ModificationStatus;

use std::ffi::c_void;
use std::marker::PhantomData;
use std::mem;
use std::mem::MaybeUninit;
use std::os::raw::c_void;
use std::ptr;
use std::slice;

Expand Down
67 changes: 30 additions & 37 deletions rust/src/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,16 @@
use binaryninjacore_sys::*;

use crate::{
binaryview::BinaryView,
platform::Platform,
rc::*,
string::{raw_to_string, BnStrCompatible, BnString},
types::{DataVariableAndName, NameAndType, NamedTypedVariable, Type},
};
use crate::binaryview::BinaryView;
use crate::platform::Platform;
use crate::rc::*;
use crate::string::{raw_to_string, BnStrCompatible, BnString};
use crate::types::{DataVariableAndName, NameAndType, NamedTypedVariable, Type};

use std::{hash::Hash, os::raw::c_void, ptr, slice};
use std::ffi::{c_char, c_void};
use std::hash::Hash;
use std::ptr;
use std::slice;

struct ProgressContext(Option<Box<dyn Fn(usize, usize) -> Result<(), ()>>>);

Expand Down Expand Up @@ -311,14 +312,11 @@ impl From<&BNDebugFunctionInfo> for DebugFunctionInfo {
.map(|component| raw_to_string(*component as *const _).unwrap())
.collect();

let local_variables: Vec<NamedTypedVariable> = unsafe { slice::from_raw_parts(raw.localVariables, raw.localVariableN) }
.iter()
.map(|local_variable| {
unsafe {
NamedTypedVariable::from_raw(local_variable)
}
})
.collect();
let local_variables: Vec<NamedTypedVariable> =
unsafe { slice::from_raw_parts(raw.localVariables, raw.localVariableN) }
.iter()
.map(|local_variable| unsafe { NamedTypedVariable::from_raw(local_variable) })
.collect();

Self {
short_name: raw_to_string(raw.shortName),
Expand Down Expand Up @@ -433,10 +431,7 @@ impl DebugInfo {
}

/// Returns a generator of all functions provided by a named DebugInfoParser
pub fn functions_by_name<S: BnStrCompatible>(
&self,
parser_name: S
) -> Vec<DebugFunctionInfo> {
pub fn functions_by_name<S: BnStrCompatible>(&self, parser_name: S) -> Vec<DebugFunctionInfo> {
let parser_name = parser_name.into_bytes_with_nul();

let mut count: usize = 0;
Expand Down Expand Up @@ -754,8 +749,7 @@ impl DebugInfo {
new_type: &Type,
components: &[&str],
) -> bool {
let mut components_array: Vec<*const ::std::os::raw::c_char> =
Vec::with_capacity(components.len());
let mut components_array: Vec<*const c_char> = Vec::with_capacity(components.len());
for component in components {
components_array.push(component.as_ptr() as _);
}
Expand Down Expand Up @@ -787,28 +781,28 @@ impl DebugInfo {
.as_ref()
.map_or(ptr::null_mut() as *mut _, |name| name.as_ptr() as _);

let mut components_array: Vec<*mut ::std::os::raw::c_char> =
Vec::with_capacity(new_func.components.len());

let mut components_array: Vec<*mut c_char> = Vec::with_capacity(new_func.components.len());

let mut local_variables_array: Vec<BNVariableNameAndType> =
Vec::with_capacity(new_func.local_variables.len());

unsafe {
for component in &new_func.components {
components_array.push(BNAllocString(component.clone().into_bytes_with_nul().as_ptr() as _));
components_array.push(BNAllocString(
component.clone().into_bytes_with_nul().as_ptr() as _,
));
}

for local_variable in &new_func.local_variables {
local_variables_array.push(
BNVariableNameAndType {
var: local_variable.var.raw(),
autoDefined: local_variable.auto_defined,
typeConfidence: local_variable.ty.confidence,
name: BNAllocString(local_variable.name.clone().into_bytes_with_nul().as_ptr() as _),
type_: local_variable.ty.contents.handle,
}
);
local_variables_array.push(BNVariableNameAndType {
var: local_variable.var.raw(),
autoDefined: local_variable.auto_defined,
typeConfidence: local_variable.ty.confidence,
name: BNAllocString(
local_variable.name.clone().into_bytes_with_nul().as_ptr() as _
),
type_: local_variable.ty.contents.handle,
});
}

let result = BNAddDebugFunction(
Expand Down Expand Up @@ -852,8 +846,7 @@ impl DebugInfo {
name: Option<S>,
components: &[&str],
) -> bool {
let mut components_array: Vec<*const ::std::os::raw::c_char> =
Vec::with_capacity(components.len());
let mut components_array: Vec<*const c_char> = Vec::with_capacity(components.len());
for component in components {
components_array.push(component.as_ptr() as _);
}
Expand Down
16 changes: 6 additions & 10 deletions rust/src/demangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,20 @@
//! Interfaces for demangling and simplifying mangled names in binaries.
use binaryninjacore_sys::*;
use std::os::raw::c_char;
use std::{ffi::CStr, result};
use std::ffi::{c_char, CStr};

use crate::architecture::CoreArchitecture;
use crate::string::{BnStrCompatible, BnString};
use crate::types::Type;

use crate::rc::*;

pub type Result<R> = result::Result<R, ()>;
pub type Result<R> = std::result::Result<R, ()>;

pub fn demangle_llvm<S: BnStrCompatible>(
mangled_name: S,
simplify: bool,
) -> Result<Vec<String>> {
pub fn demangle_llvm<S: BnStrCompatible>(mangled_name: S, simplify: bool) -> Result<Vec<String>> {
let mangled_name_bwn = mangled_name.into_bytes_with_nul();
let mangled_name_ptr = mangled_name_bwn.as_ref();
let mut out_name: *mut *mut std::os::raw::c_char = unsafe { std::mem::zeroed() };
let mut out_name: *mut *mut c_char = unsafe { std::mem::zeroed() };
let mut out_size: usize = 0;
let res = unsafe {
BNDemangleLLVM(
Expand Down Expand Up @@ -77,7 +73,7 @@ pub fn demangle_gnu3<S: BnStrCompatible>(
let mangled_name_bwn = mangled_name.into_bytes_with_nul();
let mangled_name_ptr = mangled_name_bwn.as_ref();
let mut out_type: *mut BNType = std::ptr::null_mut();
let mut out_name: *mut *mut std::os::raw::c_char = std::ptr::null_mut();
let mut out_name: *mut *mut c_char = std::ptr::null_mut();
let mut out_size: usize = 0;
let res = unsafe {
BNDemangleGNU3(
Expand Down Expand Up @@ -133,7 +129,7 @@ pub fn demangle_ms<S: BnStrCompatible>(
let mangled_name_ptr = mangled_name_bwn.as_ref();

let mut out_type: *mut BNType = std::ptr::null_mut();
let mut out_name: *mut *mut std::os::raw::c_char = std::ptr::null_mut();
let mut out_name: *mut *mut c_char = std::ptr::null_mut();
let mut out_size: usize = 0;
let res = unsafe {
BNDemangleMS(
Expand Down
Loading

0 comments on commit 35d8650

Please sign in to comment.