diff options
| -rw-r--r-- | architecture.cpp | 2 | ||||
| -rw-r--r-- | binaryninjaapi.h | 4 | ||||
| -rw-r--r-- | binaryninjacore.h | 4 | ||||
| -rw-r--r-- | callingconvention.cpp | 2 | ||||
| -rw-r--r-- | python/architecture.py | 2 | ||||
| -rw-r--r-- | python/callingconvention.py | 2 | ||||
| -rw-r--r-- | rust/src/architecture.rs | 134 | ||||
| -rw-r--r-- | rust/src/callingconvention.rs | 69 |
8 files changed, 126 insertions, 93 deletions
diff --git a/architecture.cpp b/architecture.cpp index e0617b93..75ab3d0a 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -530,7 +530,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; } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 4d759a17..c857919c 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -7940,7 +7940,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); @@ -15026,7 +15026,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); diff --git a/binaryninjacore.h b/binaryninjacore.h index da068fbe..8dcab816 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1862,7 +1862,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); @@ -2541,7 +2541,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); diff --git a/callingconvention.cpp b/callingconvention.cpp index 50cf5062..171ef953 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -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; } diff --git a/python/architecture.py b/python/architecture.py index ec65b92e..abcfb015 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -999,7 +999,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): 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: diff --git a/python/callingconvention.py b/python/callingconvention.py index ce722e80..43be2bf5 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -281,7 +281,7 @@ class CallingConvention: 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: diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index b5a1cfdb..e91925b7 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -1941,34 +1941,19 @@ 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 @@ -1976,9 +1961,13 @@ 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 @@ -1986,9 +1975,13 @@ 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 @@ -1996,9 +1989,13 @@ 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 @@ -2006,9 +2003,13 @@ 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 @@ -2016,9 +2017,13 @@ 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 @@ -2026,9 +2031,13 @@ 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 @@ -2036,9 +2045,13 @@ 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 @@ -2068,9 +2081,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>( @@ -2084,8 +2101,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; @@ -2153,8 +2175,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; @@ -2285,15 +2312,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); } } @@ -2362,9 +2387,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>( @@ -2420,8 +2449,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>( diff --git a/rust/src/callingconvention.rs b/rust/src/callingconvention.rs index a009b439..915bdcc2 100644 --- a/rust/src/callingconvention.rs +++ b/rust/src/callingconvention.rs @@ -81,34 +81,13 @@ where }) } - 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 { - return ptr::null_mut(); - } - - let res: Box<[_]> = [len as u32].into_iter().chain(items).collect(); - debug_assert!(res.len() == len + 1); - - // it's free on the function below: `cb_free_register_list` - let raw = Box::leak(res); - &mut raw[1] - } - - 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) { ffi_wrap!("CallingConvention::free_register_list", unsafe { if regs.is_null() { return; } - - let actual_start = regs.offset(-1); - let len = (*actual_start) + 1; - let _regs = Box::from_raw(ptr::slice_from_raw_parts_mut(actual_start, len as usize)); + + let _regs = Box::from_raw(ptr::slice_from_raw_parts_mut(regs, count)); }) } @@ -118,9 +97,13 @@ where { ffi_wrap!("CallingConvention::caller_saved_registers", unsafe { let ctxt = &*(ctxt as *mut CustomCallingConventionContext<C>); - let regs = ctxt.cc.caller_saved_registers(); + let mut regs = ctxt.cc.caller_saved_registers(); - alloc_register_list(regs.iter().map(|r| r.id()), &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 _ }) } @@ -130,9 +113,13 @@ where { ffi_wrap!("CallingConvention::callee_saved_registers", unsafe { let ctxt = &*(ctxt as *mut CustomCallingConventionContext<C>); - let regs = ctxt.cc.callee_saved_registers(); - - alloc_register_list(regs.iter().map(|r| r.id()), &mut *count) + let mut regs = ctxt.cc.callee_saved_registers(); + + // SAFETY: `count` is an out parameter + unsafe { *count = regs.len() }; + let regs_ptr = regs.as_mut_ptr(); + mem::forget(regs); + regs_ptr as *mut _ }) } @@ -142,9 +129,13 @@ where { ffi_wrap!("CallingConvention::int_arg_registers", unsafe { let ctxt = &*(ctxt as *mut CustomCallingConventionContext<C>); - let regs = ctxt.cc.int_arg_registers(); + let mut regs = ctxt.cc.int_arg_registers(); - alloc_register_list(regs.iter().map(|r| r.id()), &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 _ }) } @@ -154,9 +145,13 @@ where { ffi_wrap!("CallingConvention::float_arg_registers", unsafe { let ctxt = &*(ctxt as *mut CustomCallingConventionContext<C>); - let regs = ctxt.cc.float_arg_registers(); + let mut regs = ctxt.cc.float_arg_registers(); - alloc_register_list(regs.iter().map(|r| r.id()), &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 _ }) } @@ -272,9 +267,13 @@ where { ffi_wrap!("CallingConvention::implicitly_defined_registers", unsafe { let ctxt = &*(ctxt as *mut CustomCallingConventionContext<C>); - let regs = ctxt.cc.implicitly_defined_registers(); + let mut regs = ctxt.cc.implicitly_defined_registers(); - alloc_register_list(regs.iter().map(|r| r.id()), &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 _ }) } |
