Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify Guard API and reduce its use in CoreArrayProvider #5880

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c8589a3
Delete duplicate rust example
emesare Jul 28, 2024
248bfd4
Untrack Cargo.lock for rust libraries
emesare Jul 28, 2024
a5a2c75
Add MSRV field to Cargo.toml
emesare Jul 28, 2024
472bca1
Misc changes to rust README
emesare Jul 28, 2024
73d58a0
Add FindRust cmake utility
emesare Jul 29, 2024
8a24a43
Link core in rust
emesare Jul 29, 2024
d4df5ca
Use /bin/cat as the example binary in docs
emesare Jul 29, 2024
f2d7542
Fix crash when using projects API in rust with enterprise
emesare Jul 29, 2024
995ec20
Canonicalize path in `create_delete_empty` test
emesare Jul 29, 2024
4b686d2
Mark well-formed doc snippets as runnable in rust api
emesare Jul 29, 2024
b93b2ce
Revert temporary fix for enterprise crashing on rust project API
emesare Jul 29, 2024
db2ee69
Fix project tests in rust accessing to the same single project file
emesare Jul 29, 2024
3bdc4ef
Remove vendored pdb crate
emesare Jul 29, 2024
00a1ee5
Remove Cargo.lock from examples
emesare Jul 29, 2024
1cbfb03
Format rust api
emesare Jul 30, 2024
e2a57bb
improve the CustomBinaryView init process
rbran May 6, 2024
bdbd96a
Reference type within rust docs
emesare Jul 30, 2024
dc4a204
Update lib.rs docs on building/linking a plugin or script
emesare Jul 30, 2024
21fd88d
Reference types in BnString docs
emesare Jul 31, 2024
ec43516
Pass length to free register list callback
emesare Aug 1, 2024
ce5995c
Pass length to free flag conditions list callback and remove libc fro…
emesare Aug 1, 2024
9bddf13
Simplify `Guard` API and reduce its use in `CoreArrayProvider`
mkrasnitski Jul 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Pass length to free register list callback
Allows language bindings like rust to free register lists sanely
  • Loading branch information
emesare committed Aug 1, 2024
commit ec43516f6c9eb0482e13626bb205c149d75d1bf4
2 changes: 1 addition & 1 deletion architecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ size_t Architecture::GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t
}


void Architecture::FreeRegisterListCallback(void*, uint32_t* regs)
void Architecture::FreeRegisterListCallback(void*, uint32_t* regs, size_t)
{
delete[] regs;
}
Expand Down
4 changes: 2 additions & 2 deletions binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -7752,7 +7752,7 @@ namespace BinaryNinja {
static size_t GetFlagConditionLowLevelILCallback(
void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, BNLowLevelILFunction* il);
static size_t GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il);
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs);
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs, size_t len);
static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result);
static uint32_t GetStackPointerRegisterCallback(void* ctxt);
static uint32_t GetLinkRegisterCallback(void* ctxt);
Expand Down Expand Up @@ -14505,7 +14505,7 @@ namespace BinaryNinja {
static uint32_t* GetCalleeSavedRegistersCallback(void* ctxt, size_t* count);
static uint32_t* GetIntegerArgumentRegistersCallback(void* ctxt, size_t* count);
static uint32_t* GetFloatArgumentRegistersCallback(void* ctxt, size_t* count);
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs);
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs, size_t len);

static bool AreArgumentRegistersSharedIndexCallback(void* ctxt);
static bool AreArgumentRegistersUsedForVarArgsCallback(void* ctxt);
Expand Down
8 changes: 4 additions & 4 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 71
#define BN_CURRENT_CORE_ABI_VERSION 72

// 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 71
#define BN_MINIMUM_CORE_ABI_VERSION 72

#ifdef __GNUC__
#ifdef BINARYNINJACORE_LIBRARY
Expand Down Expand Up @@ -1839,7 +1839,7 @@ extern "C"
size_t (*getFlagConditionLowLevelIL)(
void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, BNLowLevelILFunction* il);
size_t (*getSemanticFlagGroupLowLevelIL)(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il);
void (*freeRegisterList)(void* ctxt, uint32_t* regs);
void (*freeRegisterList)(void* ctxt, uint32_t* regs, size_t count);
void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result);
uint32_t (*getStackPointerRegister)(void* ctxt);
uint32_t (*getLinkRegister)(void* ctxt);
Expand Down Expand Up @@ -2518,7 +2518,7 @@ extern "C"
uint32_t* (*getCalleeSavedRegisters)(void* ctxt, size_t* count);
uint32_t* (*getIntegerArgumentRegisters)(void* ctxt, size_t* count);
uint32_t* (*getFloatArgumentRegisters)(void* ctxt, size_t* count);
void (*freeRegisterList)(void* ctxt, uint32_t* regs);
void (*freeRegisterList)(void* ctxt, uint32_t* regs, size_t len);

bool (*areArgumentRegistersSharedIndex)(void* ctxt);
bool (*isStackReservedForArgumentRegisters)(void* ctxt);
Expand Down
2 changes: 1 addition & 1 deletion callingconvention.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ uint32_t* CallingConvention::GetFloatArgumentRegistersCallback(void* ctxt, size_
}


void CallingConvention::FreeRegisterListCallback(void*, uint32_t* regs)
void CallingConvention::FreeRegisterListCallback(void*, uint32_t* regs, size_t)
{
delete[] regs;
}
Expand Down
2 changes: 1 addition & 1 deletion python/architecture.py
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ def _get_semantic_flag_group_low_level_il(self, ctxt, sem_group, il):
log_error(traceback.format_exc())
return 0

def _free_register_list(self, ctxt, regs):
def _free_register_list(self, ctxt, regs, count):
try:
buf = ctypes.cast(regs, ctypes.c_void_p)
if buf.value not in self._pending_reg_lists:
Expand Down
2 changes: 1 addition & 1 deletion python/callingconvention.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def _get_float_arg_regs(self, ctxt, count):
count[0] = 0
return None

def _free_register_list(self, ctxt, regs):
def _free_register_list(self, ctxt, regs, count):
try:
buf = ctypes.cast(regs, ctypes.c_void_p)
if buf.value not in self._pending_reg_lists:
Expand Down
134 changes: 84 additions & 50 deletions rust/src/architecture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1940,104 +1940,117 @@ where
None => BnString::new("invalid_flag_group").into_raw(),
}
}

fn alloc_register_list<I: Iterator<Item = u32> + ExactSizeIterator>(
items: I,
count: &mut usize,
) -> *mut u32 {
let len = items.len();
*count = len;

if len == 0 {
ptr::null_mut()
} else {
let mut res: Box<[_]> = [len as u32].into_iter().chain(items).collect();

let raw = res.as_mut_ptr();
mem::forget(res);

unsafe { raw.offset(1) }
}
}


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 regs = custom_arch.registers_full_width();
let mut regs = custom_arch.registers_full_width();

alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
}

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 regs = custom_arch.registers_all();
let mut regs = custom_arch.registers_all();

alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
}

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 regs = custom_arch.registers_global();
let mut regs = custom_arch.registers_global();

alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
}

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 regs = custom_arch.registers_system();
let mut regs = custom_arch.registers_system();

alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
}

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 flags = custom_arch.flags();
let mut flags = custom_arch.flags();

alloc_register_list(flags.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let regs_ptr = flags.as_mut_ptr();
mem::forget(flags);
regs_ptr as *mut _
}

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 flag_writes = custom_arch.flag_write_types();
let mut flag_writes = custom_arch.flag_write_types();

alloc_register_list(flag_writes.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = flag_writes.len() };
let regs_ptr = flag_writes.as_mut_ptr();
mem::forget(flag_writes);
regs_ptr as *mut _
}

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 flag_classes = custom_arch.flag_classes();
let mut flag_classes = custom_arch.flag_classes();

alloc_register_list(flag_classes.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = flag_classes.len() };
let regs_ptr = flag_classes.as_mut_ptr();
mem::forget(flag_classes);
regs_ptr as *mut _
}

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 flag_groups = custom_arch.flag_groups();
let mut flag_groups = custom_arch.flag_groups();

alloc_register_list(flag_groups.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = flag_groups.len() };
let regs_ptr = flag_groups.as_mut_ptr();
mem::forget(flag_groups);
regs_ptr as *mut _
}

extern "C" fn cb_flag_role<A>(ctxt: *mut c_void, flag: u32, class: u32) -> BNFlagRole
Expand Down Expand Up @@ -2067,9 +2080,13 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let class = custom_arch.flag_class_from_id(class);
let flags = custom_arch.flags_required_for_flag_condition(cond, class);
let mut flags = custom_arch.flags_required_for_flag_condition(cond, class);

alloc_register_list(flags.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let regs_ptr = flags.as_mut_ptr();
mem::forget(flags);
regs_ptr as *mut _
}

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

if let Some(group) = custom_arch.flag_group_from_id(group) {
let flags = group.flags_required();
alloc_register_list(flags.iter().map(|r| r.id()), unsafe { &mut *count })
let mut flags = group.flags_required();

// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let regs_ptr = flags.as_mut_ptr();
mem::forget(flags);
regs_ptr as *mut _
} else {
unsafe {
*count = 0;
Expand Down Expand Up @@ -2152,8 +2174,13 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };

if let Some(write_type) = custom_arch.flag_write_from_id(write_type) {
let written = write_type.flags_written();
alloc_register_list(written.iter().map(|f| f.id()), unsafe { &mut *count })
let mut written = write_type.flags_written();

// SAFETY: `count` is an out parameter
unsafe { *count = written.len() };
let regs_ptr = written.as_mut_ptr();
mem::forget(written);
regs_ptr as *mut _
} else {
unsafe {
*count = 0;
Expand Down Expand Up @@ -2284,15 +2311,13 @@ where
lifter.unimplemented().expr_idx
}

extern "C" fn cb_free_register_list(_ctxt: *mut c_void, regs: *mut u32) {
extern "C" fn cb_free_register_list(_ctxt: *mut c_void, regs: *mut u32, count: usize) {
if regs.is_null() {
return;
}

unsafe {
let actual_start = regs.offset(-1);
let len = *actual_start + 1;
let regs_ptr = ptr::slice_from_raw_parts_mut(actual_start, len.try_into().unwrap());
let regs_ptr = ptr::slice_from_raw_parts_mut(regs, count);
let _regs = Box::from_raw(regs_ptr);
}
}
Expand Down Expand Up @@ -2361,9 +2386,13 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
let regs = custom_arch.register_stacks();
let mut regs = custom_arch.register_stacks();

alloc_register_list(regs.iter().map(|r| r.id()), unsafe { &mut *count })
// SAFETY: Passed in to be written
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
mem::forget(regs);
regs_ptr as *mut _
}

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

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

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