Skip to content

Commit

Permalink
Pass length to free flag conditions list callback and remove libc fro…
Browse files Browse the repository at this point in the history
…m rust api

Allows language bindings like rust to free conditions lists sanely
  • Loading branch information
emesare committed Dec 14, 2024
1 parent 121c165 commit b34ddd0
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 93 deletions.
1 change: 0 additions & 1 deletion arch/msp430/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 arch/riscv/Cargo.lock

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

2 changes: 1 addition & 1 deletion architecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ BNFlagConditionForSemanticClass* Architecture::GetFlagConditionsForSemanticFlagG
}


void Architecture::FreeFlagConditionsForSemanticFlagGroupCallback(void*, BNFlagConditionForSemanticClass* conditions)
void Architecture::FreeFlagConditionsForSemanticFlagGroupCallback(void*, BNFlagConditionForSemanticClass* conditions, size_t)
{
delete[] conditions;
}
Expand Down
2 changes: 1 addition & 1 deletion binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -7931,7 +7931,7 @@ namespace BinaryNinja {
static BNFlagConditionForSemanticClass* GetFlagConditionsForSemanticFlagGroupCallback(
void* ctxt, uint32_t semGroup, size_t* count);
static void FreeFlagConditionsForSemanticFlagGroupCallback(
void* ctxt, BNFlagConditionForSemanticClass* conditions);
void* ctxt, BNFlagConditionForSemanticClass* conditions, size_t count);
static uint32_t* GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint32_t writeType, size_t* count);
static uint32_t GetSemanticClassForFlagWriteTypeCallback(void* ctxt, uint32_t writeType);
static size_t GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOperation op, size_t size,
Expand Down
6 changes: 3 additions & 3 deletions binaryninjacore.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
// Current ABI version for linking to the core. This is incremented any time
// there are changes to the API that affect linking, including new functions,
// new types, or modifications to existing functions or types.
#define BN_CURRENT_CORE_ABI_VERSION 85
#define BN_CURRENT_CORE_ABI_VERSION 86

// Minimum ABI version that is supported for loading of plugins. Plugins that
// are linked to an ABI version less than this will not be able to load and
// will require rebuilding. The minimum version is increased when there are
// incompatible changes that break binary compatibility, such as changes to
// existing types or functions.
#define BN_MINIMUM_CORE_ABI_VERSION 82
#define BN_MINIMUM_CORE_ABI_VERSION 86

#ifdef __GNUC__
#ifdef BINARYNINJACORE_LIBRARY
Expand Down Expand Up @@ -1854,7 +1854,7 @@ extern "C"
uint32_t* (*getFlagsRequiredForSemanticFlagGroup)(void* ctxt, uint32_t semGroup, size_t* count);
BNFlagConditionForSemanticClass* (*getFlagConditionsForSemanticFlagGroup)(
void* ctxt, uint32_t semGroup, size_t* count);
void (*freeFlagConditionsForSemanticFlagGroup)(void* ctxt, BNFlagConditionForSemanticClass* conditions);
void (*freeFlagConditionsForSemanticFlagGroup)(void* ctxt, BNFlagConditionForSemanticClass* conditions, size_t count);
uint32_t* (*getFlagsWrittenByFlagWriteType)(void* ctxt, uint32_t writeType, size_t* count);
uint32_t (*getSemanticClassForFlagWriteType)(void* ctxt, uint32_t writeType);
size_t (*getFlagWriteLowLevelIL)(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
Expand Down
2 changes: 1 addition & 1 deletion python/architecture.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ def _get_flag_conditions_for_semantic_flag_group(self, ctxt, sem_group, count):
count[0] = 0
return None

def _free_flag_conditions_for_semantic_flag_group(self, ctxt, conditions):
def _free_flag_conditions_for_semantic_flag_group(self, ctxt, conditions, count):
try:
buf = ctypes.cast(conditions, ctypes.c_void_p)
if buf.value not in self._pending_condition_lists:
Expand Down
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 @@ -11,7 +11,6 @@ noexports = []
[dependencies]
lazy_static = "1.4.0"
log = { version = "0.4", features = ["std"] }
libc = "0.2"
rayon = { version = "1.8", optional = true }
binaryninjacore-sys = { path = "binaryninjacore-sys" }

Expand Down
141 changes: 84 additions & 57 deletions rust/src/architecture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1941,117 +1941,133 @@ where
None => BnString::new("invalid_flag_group").into_raw(),
}
}

extern "C" fn cb_registers_full_width<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut regs = custom_arch.registers_full_width();
let mut regs: Vec<_> = custom_arch
.registers_full_width()
.iter()
.map(|r| r.id())
.collect();

// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
regs_ptr
}

extern "C" fn cb_registers_all<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut regs = custom_arch.registers_all();
let mut regs: Vec<_> = custom_arch.registers_all().iter().map(|r| r.id()).collect();

// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
regs_ptr
}

extern "C" fn cb_registers_global<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut regs = custom_arch.registers_global();
let mut regs: Vec<_> = custom_arch
.registers_global()
.iter()
.map(|r| r.id())
.collect();

// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
regs_ptr
}

extern "C" fn cb_registers_system<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut regs = custom_arch.registers_system();
let mut regs: Vec<_> = custom_arch
.registers_system()
.iter()
.map(|r| r.id())
.collect();

// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
regs_ptr
}

extern "C" fn cb_flags<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut flags = custom_arch.flags();
let mut flags: Vec<_> = custom_arch.flags().iter().map(|f| f.id()).collect();

// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let regs_ptr = flags.as_mut_ptr();
let flags_ptr = flags.as_mut_ptr();
mem::forget(flags);
regs_ptr as *mut _
flags_ptr
}

extern "C" fn cb_flag_write_types<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut flag_writes = custom_arch.flag_write_types();
let mut flag_writes: Vec<_> = custom_arch
.flag_write_types()
.iter()
.map(|f| f.id())
.collect();

// SAFETY: `count` is an out parameter
unsafe { *count = flag_writes.len() };
let regs_ptr = flag_writes.as_mut_ptr();
let flags_ptr = flag_writes.as_mut_ptr();
mem::forget(flag_writes);
regs_ptr as *mut _
flags_ptr
}

extern "C" fn cb_semantic_flag_classes<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut flag_classes = custom_arch.flag_classes();
let mut flag_classes: Vec<_> = custom_arch.flag_classes().iter().map(|f| f.id()).collect();

// SAFETY: `count` is an out parameter
unsafe { *count = flag_classes.len() };
let regs_ptr = flag_classes.as_mut_ptr();
let flags_ptr = flag_classes.as_mut_ptr();
mem::forget(flag_classes);
regs_ptr as *mut _
flags_ptr
}

extern "C" fn cb_semantic_flag_groups<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut flag_groups = custom_arch.flag_groups();
let mut flag_groups: Vec<_> = custom_arch.flag_groups().iter().map(|f| f.id()).collect();

// SAFETY: `count` is an out parameter
unsafe { *count = flag_groups.len() };
let regs_ptr = flag_groups.as_mut_ptr();
let flags_ptr = flag_groups.as_mut_ptr();
mem::forget(flag_groups);
regs_ptr as *mut _
flags_ptr
}

extern "C" fn cb_flag_role<A>(ctxt: *mut c_void, flag: u32, class: u32) -> BNFlagRole
Expand Down Expand Up @@ -2081,13 +2097,17 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let class = custom_arch.flag_class_from_id(class);
let mut flags = custom_arch.flags_required_for_flag_condition(cond, class);
let mut flags: Vec<_> = custom_arch
.flags_required_for_flag_condition(cond, class)
.iter()
.map(|f| f.id())
.collect();

// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let regs_ptr = flags.as_mut_ptr();
let flags_ptr = flags.as_mut_ptr();
mem::forget(flags);
regs_ptr as *mut _
flags_ptr
}

extern "C" fn cb_flags_required_for_semantic_flag_group<A>(
Expand All @@ -2101,13 +2121,13 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };

if let Some(group) = custom_arch.flag_group_from_id(group) {
let mut flags = group.flags_required();
let mut flags: Vec<_> = group.flags_required().iter().map(|f| f.id()).collect();

// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let regs_ptr = flags.as_mut_ptr();
let flags_ptr = flags.as_mut_ptr();
mem::forget(flags);
regs_ptr as *mut _
flags_ptr
} else {
unsafe {
*count = 0;
Expand All @@ -2128,23 +2148,19 @@ where

if let Some(group) = custom_arch.flag_group_from_id(group) {
let flag_conditions = group.flag_conditions();
let mut flags = flag_conditions
.iter()
.map(|(&class, &condition)| BNFlagConditionForSemanticClass {
semanticClass: class.id(),
condition,
})
.collect::<Vec<_>>();

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());

for (i, (class, cond)) in flag_conditions.iter().enumerate() {
let out = out_slice.get_unchecked_mut(i);

out.semanticClass = class.id();
out.condition = *cond;
}

*count = flag_conditions.len();
result
}
// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let flags_ptr = flags.as_mut_ptr();
mem::forget(flags);
flags_ptr
} else {
unsafe {
*count = 0;
Expand All @@ -2156,11 +2172,17 @@ where
extern "C" fn cb_free_flag_conditions_for_semantic_flag_group<A>(
_ctxt: *mut c_void,
conds: *mut BNFlagConditionForSemanticClass,
count: usize,
) where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
if conds.is_null() {
return;
}

unsafe {
libc::free(conds as *mut _);
let flags_ptr = ptr::slice_from_raw_parts_mut(conds, count);
let _flags = Box::from_raw(flags_ptr);
}
}

Expand All @@ -2175,13 +2197,14 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };

if let Some(write_type) = custom_arch.flag_write_from_id(write_type) {
let mut written = write_type.flags_written();

let mut flags_written: Vec<_> =
write_type.flags_written().iter().map(|f| f.id()).collect();

// SAFETY: `count` is an out parameter
unsafe { *count = written.len() };
let regs_ptr = written.as_mut_ptr();
mem::forget(written);
regs_ptr as *mut _
unsafe { *count = flags_written.len() };
let flags_ptr = flags_written.as_mut_ptr();
mem::forget(flags_written);
flags_ptr
} else {
unsafe {
*count = 0;
Expand Down Expand Up @@ -2387,13 +2410,17 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut regs = custom_arch.register_stacks();
let mut regs: Vec<_> = custom_arch
.register_stacks()
.iter()
.map(|r| r.id())
.collect();

// SAFETY: Passed in to be written
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
regs_ptr
}

extern "C" fn cb_reg_stack_info<A>(
Expand Down Expand Up @@ -2449,13 +2476,13 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let mut intrinsics = custom_arch.intrinsics();
let mut intrinsics: Vec<_> = custom_arch.intrinsics().iter().map(|i| i.id()).collect();

// SAFETY: Passed in to be written
unsafe { *count = intrinsics.len() };
let regs_ptr = intrinsics.as_mut_ptr();
let intrinsics_ptr = intrinsics.as_mut_ptr();
mem::forget(intrinsics);
regs_ptr as *mut _
intrinsics_ptr
}

extern "C" fn cb_intrinsic_inputs<A>(
Expand Down
Loading

0 comments on commit b34ddd0

Please sign in to comment.