summaryrefslogtreecommitdiff
path: root/rust/src/function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/function.rs')
-rw-r--r--rust/src/function.rs1169
1 files changed, 766 insertions, 403 deletions
diff --git a/rust/src/function.rs b/rust/src/function.rs
index 0df9fcf5..b524edfb 100644
--- a/rust/src/function.rs
+++ b/rust/src/function.rs
@@ -16,41 +16,58 @@ use binaryninjacore_sys::*;
use crate::{
architecture::{Architecture, CoreArchitecture, CoreRegister, Register},
- basicblock::{BasicBlock, BlockContext},
- binaryview::{BinaryView, BinaryViewExt},
- callingconvention::CallingConvention,
+ basic_block::{BasicBlock, BlockContext},
+ binary_view::{BinaryView, BinaryViewExt},
+ calling_convention::CoreCallingConvention,
component::Component,
disassembly::{DisassemblySettings, DisassemblyTextLine},
flowgraph::FlowGraph,
- hlil, llil,
- mlil::{self, FunctionGraphType},
+ medium_level_il::FunctionGraphType,
platform::Platform,
references::CodeReference,
string::*,
symbol::Symbol,
tags::{Tag, TagReference, TagType},
- types::{
- Conf, ConstantReference, HighlightColor, IndirectBranchInfo, IntegerDisplayType,
- MergedVariable, NamedTypedVariable, QualifiedName, RegisterStackAdjustment, RegisterValue,
- RegisterValueType, StackVariableReference, Type, UnresolvedIndirectBranches, Variable,
- },
+ types::{IntegerDisplayType, QualifiedName, Type},
};
-use crate::{databuffer::DataBuffer, disassembly::InstructionTextToken, rc::*};
+use crate::{data_buffer::DataBuffer, disassembly::InstructionTextToken, rc::*};
pub use binaryninjacore_sys::BNAnalysisSkipReason as AnalysisSkipReason;
+pub use binaryninjacore_sys::BNBuiltinType as BuiltinType;
pub use binaryninjacore_sys::BNFunctionAnalysisSkipOverride as FunctionAnalysisSkipOverride;
pub use binaryninjacore_sys::BNFunctionUpdateType as FunctionUpdateType;
-pub use binaryninjacore_sys::BNBuiltinType as BuiltinType;
+pub use binaryninjacore_sys::BNHighlightStandardColor as HighlightStandardColor;
-use std::{fmt, mem};
-use std::{ffi::c_char, hash::Hash, ops::Range};
-use std::ptr::NonNull;
+use crate::architecture::RegisterId;
+use crate::confidence::Conf;
+use crate::high_level_il::HighLevelILFunction;
+use crate::low_level_il::{LiftedILFunction, RegularLowLevelILFunction};
+use crate::medium_level_il::MediumLevelILFunction;
+use crate::variable::{
+ IndirectBranchInfo, MergedVariable, NamedVariableWithType, RegisterValue, RegisterValueType,
+ StackVariableReference, Variable,
+};
use crate::workflow::Workflow;
+use std::fmt::{Debug, Formatter};
+use std::ptr::NonNull;
+use std::time::Duration;
+use std::{ffi::c_char, hash::Hash, ops::Range};
+/// Used to describe a location within a [`Function`].
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Location {
pub arch: Option<CoreArchitecture>,
pub addr: u64,
}
+impl Location {
+ pub(crate) fn from_raw(addr: u64, arch: *mut BNArchitecture) -> Self {
+ Self {
+ addr,
+ arch: Some(unsafe { CoreArchitecture::from_raw(arch) }),
+ }
+ }
+}
+
impl From<u64> for Location {
fn from(addr: u64) -> Self {
Location { arch: None, addr }
@@ -66,6 +83,21 @@ impl From<(CoreArchitecture, u64)> for Location {
}
}
+impl From<BNArchitectureAndAddress> for Location {
+ fn from(value: BNArchitectureAndAddress) -> Self {
+ Self::from_raw(value.address, value.arch)
+ }
+}
+
+impl From<Location> for BNArchitectureAndAddress {
+ fn from(value: Location) -> Self {
+ Self {
+ arch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()),
+ address: value.addr,
+ }
+ }
+}
+
pub struct NativeBlockIter {
arch: CoreArchitecture,
bv: Ref<BinaryView>,
@@ -108,19 +140,20 @@ impl NativeBlock {
}
impl BlockContext for NativeBlock {
- type Iter = NativeBlockIter;
type Instruction = u64;
+ type InstructionIndex = u64;
+ type Iter = NativeBlockIter;
fn start(&self, block: &BasicBlock<Self>) -> u64 {
- block.raw_start()
+ block.start_index()
}
fn iter(&self, block: &BasicBlock<Self>) -> NativeBlockIter {
NativeBlockIter {
arch: block.arch(),
bv: block.function().view(),
- cur: block.raw_start(),
- end: block.raw_end(),
+ cur: block.start_index(),
+ end: block.end_index(),
}
}
}
@@ -140,59 +173,119 @@ pub enum FunctionViewType {
HighLevelLanguageRepresentation(String),
}
-pub(crate) struct RawFunctionViewType(pub BNFunctionViewType);
-
+#[allow(unused)]
impl FunctionViewType {
- pub(crate) fn as_raw(&self) -> RawFunctionViewType {
- let view_type = match self {
+ pub(crate) fn from_raw(value: &BNFunctionViewType) -> Option<Self> {
+ match value.type_ {
+ BNFunctionGraphType::InvalidILViewType => None,
+ BNFunctionGraphType::NormalFunctionGraph => Some(FunctionViewType::Normal),
+ BNFunctionGraphType::LowLevelILFunctionGraph => Some(FunctionViewType::LowLevelIL),
+ BNFunctionGraphType::LiftedILFunctionGraph => Some(FunctionViewType::LiftedIL),
+ BNFunctionGraphType::LowLevelILSSAFormFunctionGraph => {
+ Some(FunctionViewType::LowLevelILSSAForm)
+ }
+ BNFunctionGraphType::MediumLevelILFunctionGraph => {
+ Some(FunctionViewType::MediumLevelIL)
+ }
+ BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph => {
+ Some(FunctionViewType::MediumLevelILSSAForm)
+ }
+ BNFunctionGraphType::MappedMediumLevelILFunctionGraph => {
+ Some(FunctionViewType::MappedMediumLevelIL)
+ }
+ BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph => {
+ Some(FunctionViewType::MappedMediumLevelILSSAForm)
+ }
+ BNFunctionGraphType::HighLevelILFunctionGraph => Some(FunctionViewType::HighLevelIL),
+ BNFunctionGraphType::HighLevelILSSAFormFunctionGraph => {
+ Some(FunctionViewType::HighLevelILSSAForm)
+ }
+ BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph => {
+ Some(FunctionViewType::HighLevelLanguageRepresentation(
+ raw_to_string(value.name).unwrap(),
+ ))
+ }
+ }
+ }
+
+ pub(crate) fn from_owned_raw(value: BNFunctionViewType) -> Option<Self> {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ pub(crate) fn into_raw(value: Self) -> BNFunctionViewType {
+ let view_type = match value {
FunctionViewType::Normal => BNFunctionGraphType::NormalFunctionGraph,
FunctionViewType::LowLevelIL => BNFunctionGraphType::LowLevelILFunctionGraph,
FunctionViewType::LiftedIL => BNFunctionGraphType::LiftedILFunctionGraph,
- FunctionViewType::LowLevelILSSAForm => BNFunctionGraphType::LowLevelILSSAFormFunctionGraph,
+ FunctionViewType::LowLevelILSSAForm => {
+ BNFunctionGraphType::LowLevelILSSAFormFunctionGraph
+ }
FunctionViewType::MediumLevelIL => BNFunctionGraphType::MediumLevelILFunctionGraph,
- FunctionViewType::MediumLevelILSSAForm => BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph,
- FunctionViewType::MappedMediumLevelIL => BNFunctionGraphType::MappedMediumLevelILFunctionGraph,
- FunctionViewType::MappedMediumLevelILSSAForm => BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph,
+ FunctionViewType::MediumLevelILSSAForm => {
+ BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph
+ }
+ FunctionViewType::MappedMediumLevelIL => {
+ BNFunctionGraphType::MappedMediumLevelILFunctionGraph
+ }
+ FunctionViewType::MappedMediumLevelILSSAForm => {
+ BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph
+ }
FunctionViewType::HighLevelIL => BNFunctionGraphType::HighLevelILFunctionGraph,
- FunctionViewType::HighLevelILSSAForm => BNFunctionGraphType::HighLevelILSSAFormFunctionGraph,
- FunctionViewType::HighLevelLanguageRepresentation(_) => BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph,
+ FunctionViewType::HighLevelILSSAForm => {
+ BNFunctionGraphType::HighLevelILSSAFormFunctionGraph
+ }
+ FunctionViewType::HighLevelLanguageRepresentation(_) => {
+ BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph
+ }
+ };
+ let view_name = match value {
+ FunctionViewType::HighLevelLanguageRepresentation(name) => Some(BnString::new(name)),
+ _ => None,
};
- RawFunctionViewType(BNFunctionViewType {
+ BNFunctionViewType {
type_: view_type,
- name: if let FunctionViewType::HighLevelLanguageRepresentation(ref name) = self {
- std::ffi::CString::new(name.to_string()).unwrap().into_raw()
- } else {
- std::ptr::null()
- },
- })
+ name: view_name
+ .map(|n| BnString::into_raw(n) as *mut _)
+ .unwrap_or(std::ptr::null_mut()),
+ }
+ }
+
+ pub(crate) fn free_raw(value: BNFunctionViewType) {
+ let _ = unsafe { BnString::from_raw(value.name as *mut _) };
}
}
-impl Into<FunctionViewType> for FunctionGraphType {
- fn into(self) -> FunctionViewType {
- match self {
+impl From<FunctionGraphType> for FunctionViewType {
+ fn from(view_type: FunctionGraphType) -> Self {
+ match view_type {
BNFunctionGraphType::LowLevelILFunctionGraph => FunctionViewType::LowLevelIL,
BNFunctionGraphType::LiftedILFunctionGraph => FunctionViewType::LiftedIL,
- BNFunctionGraphType::LowLevelILSSAFormFunctionGraph => FunctionViewType::LowLevelILSSAForm,
+ BNFunctionGraphType::LowLevelILSSAFormFunctionGraph => {
+ FunctionViewType::LowLevelILSSAForm
+ }
BNFunctionGraphType::MediumLevelILFunctionGraph => FunctionViewType::MediumLevelIL,
- BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph => FunctionViewType::MediumLevelILSSAForm,
- BNFunctionGraphType::MappedMediumLevelILFunctionGraph => FunctionViewType::MappedMediumLevelIL,
- BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph => FunctionViewType::MappedMediumLevelILSSAForm,
+ BNFunctionGraphType::MediumLevelILSSAFormFunctionGraph => {
+ FunctionViewType::MediumLevelILSSAForm
+ }
+ BNFunctionGraphType::MappedMediumLevelILFunctionGraph => {
+ FunctionViewType::MappedMediumLevelIL
+ }
+ BNFunctionGraphType::MappedMediumLevelILSSAFormFunctionGraph => {
+ FunctionViewType::MappedMediumLevelILSSAForm
+ }
BNFunctionGraphType::HighLevelILFunctionGraph => FunctionViewType::HighLevelIL,
- BNFunctionGraphType::HighLevelILSSAFormFunctionGraph => FunctionViewType::HighLevelILSSAForm,
+ BNFunctionGraphType::HighLevelILSSAFormFunctionGraph => {
+ FunctionViewType::HighLevelILSSAForm
+ }
BNFunctionGraphType::HighLevelLanguageRepresentationFunctionGraph => {
- FunctionViewType::HighLevelLanguageRepresentation("Pseudo C".into()
- )
+ // Historically this was the only language representation.
+ FunctionViewType::HighLevelLanguageRepresentation("Pseudo C".into())
+ }
+ BNFunctionGraphType::InvalidILViewType | BNFunctionGraphType::NormalFunctionGraph => {
+ FunctionViewType::Normal
}
- _ => FunctionViewType::Normal,
- }
- }
-}
-
-impl Drop for RawFunctionViewType {
- fn drop(&mut self) {
- if !self.0.name.is_null() {
- unsafe { let _ = std::ffi::CString::from_raw(self.0.name as *mut _); }
}
}
}
@@ -202,11 +295,14 @@ pub struct Function {
pub(crate) handle: *mut BNFunction,
}
-unsafe impl Send for Function {}
-unsafe impl Sync for Function {}
-
impl Function {
- pub(crate) unsafe fn from_raw(handle: *mut BNFunction) -> Ref<Self> {
+ pub(crate) unsafe fn from_raw(handle: *mut BNFunction) -> Self {
+ debug_assert!(!handle.is_null());
+ Self { handle }
+ }
+
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNFunction) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
Ref::new(Self { handle })
}
@@ -227,7 +323,7 @@ impl Function {
pub fn view(&self) -> Ref<BinaryView> {
unsafe {
let view = BNGetFunctionData(self.handle);
- BinaryView::from_raw(view)
+ BinaryView::ref_from_raw(view)
}
}
@@ -301,7 +397,7 @@ impl Function {
}
/// All comments in the function
- pub fn comments(&self) -> Array<Comments> {
+ pub fn comments(&self) -> Array<Comment> {
let mut count = 0;
let lines = unsafe { BNGetCommentedAddresses(self.handle, &mut count) };
unsafe { Array::new(lines, count, self.to_owned()) }
@@ -335,14 +431,12 @@ impl Function {
) -> Option<Ref<BasicBlock<NativeBlock>>> {
let arch = arch.unwrap_or_else(|| self.arch());
unsafe {
- let block = BNGetFunctionBasicBlockAtAddress(self.handle, arch.0, addr);
+ let basic_block_ptr = BNGetFunctionBasicBlockAtAddress(self.handle, arch.handle, addr);
let context = NativeBlock { _priv: () };
-
- if block.is_null() {
- return None;
+ match basic_block_ptr.is_null() {
+ false => Some(BasicBlock::ref_from_raw(basic_block_ptr, context)),
+ true => None,
}
-
- Some(Ref::new(BasicBlock::from_raw(block, context)))
}
}
@@ -353,147 +447,135 @@ impl Function {
) -> Array<Array<InstructionTextToken>> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
- let lines = unsafe { BNGetFunctionBlockAnnotations(self.handle, arch.0, addr, &mut count) };
+ let lines =
+ unsafe { BNGetFunctionBlockAnnotations(self.handle, arch.handle, addr, &mut count) };
assert!(!lines.is_null());
unsafe { Array::new(lines, count, ()) }
}
- pub fn get_variable_name(&self, var: &Variable) -> BnString {
+ pub fn variable_name(&self, var: &Variable) -> BnString {
unsafe {
- let raw_var = var.raw();
+ let raw_var = BNVariable::from(var);
let raw_name = BNGetVariableName(self.handle, &raw_var);
BnString::from_raw(raw_name)
}
}
- pub fn high_level_il(&self, full_ast: bool) -> Result<Ref<hlil::HighLevelILFunction>, ()> {
+ pub fn high_level_il(&self, full_ast: bool) -> Result<Ref<HighLevelILFunction>, ()> {
unsafe {
- let hlil = BNGetFunctionHighLevelIL(self.handle);
-
- if hlil.is_null() {
- return Err(());
+ let hlil_ptr = BNGetFunctionHighLevelIL(self.handle);
+ match hlil_ptr.is_null() {
+ false => Ok(HighLevelILFunction::ref_from_raw(hlil_ptr, full_ast)),
+ true => Err(()),
}
-
- Ok(hlil::HighLevelILFunction::ref_from_raw(hlil, full_ast))
}
}
- pub fn high_level_il_if_available(&self) -> Option<Ref<hlil::HighLevelILFunction>> {
- let hlil = unsafe { BNGetFunctionHighLevelILIfAvailable(self.handle) };
- (!hlil.is_null()).then(|| unsafe { hlil::HighLevelILFunction::ref_from_raw(hlil, true) })
+ pub fn high_level_il_if_available(&self) -> Option<Ref<HighLevelILFunction>> {
+ let hlil_ptr = unsafe { BNGetFunctionHighLevelILIfAvailable(self.handle) };
+ match hlil_ptr.is_null() {
+ false => Some(unsafe { HighLevelILFunction::ref_from_raw(hlil_ptr, true) }),
+ true => None,
+ }
}
/// MediumLevelILFunction used to represent Function mapped medium level IL
- pub fn mapped_medium_level_il(&self) -> Result<Ref<mlil::MediumLevelILFunction>, ()> {
- let mlil = unsafe { BNGetFunctionMappedMediumLevelIL(self.handle) };
- if mlil.is_null() {
- return Err(());
+ pub fn mapped_medium_level_il(&self) -> Result<Ref<MediumLevelILFunction>, ()> {
+ let mlil_ptr = unsafe { BNGetFunctionMappedMediumLevelIL(self.handle) };
+ match mlil_ptr.is_null() {
+ false => Ok(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
+ true => Err(()),
}
- Ok(unsafe { mlil::MediumLevelILFunction::ref_from_raw(mlil) })
}
- pub fn mapped_medium_level_il_if_available(
- &self,
- ) -> Result<Ref<mlil::MediumLevelILFunction>, ()> {
- let mlil = unsafe { BNGetFunctionMappedMediumLevelILIfAvailable(self.handle) };
- if mlil.is_null() {
- return Err(());
+ pub fn mapped_medium_level_il_if_available(&self) -> Option<Ref<MediumLevelILFunction>> {
+ let mlil_ptr = unsafe { BNGetFunctionMappedMediumLevelILIfAvailable(self.handle) };
+ match mlil_ptr.is_null() {
+ false => Some(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
+ true => None,
}
- Ok(unsafe { mlil::MediumLevelILFunction::ref_from_raw(mlil) })
}
- pub fn medium_level_il(&self) -> Result<Ref<mlil::MediumLevelILFunction>, ()> {
+ pub fn medium_level_il(&self) -> Result<Ref<MediumLevelILFunction>, ()> {
unsafe {
- let mlil = BNGetFunctionMediumLevelIL(self.handle);
-
- if mlil.is_null() {
- return Err(());
+ let mlil_ptr = BNGetFunctionMediumLevelIL(self.handle);
+ match mlil_ptr.is_null() {
+ false => Ok(MediumLevelILFunction::ref_from_raw(mlil_ptr)),
+ true => Err(()),
}
-
- Ok(mlil::MediumLevelILFunction::ref_from_raw(mlil))
}
}
- pub fn medium_level_il_if_available(&self) -> Option<Ref<mlil::MediumLevelILFunction>> {
- let mlil = unsafe { BNGetFunctionMediumLevelILIfAvailable(self.handle) };
- (!mlil.is_null()).then(|| unsafe { mlil::MediumLevelILFunction::ref_from_raw(mlil) })
+ pub fn medium_level_il_if_available(&self) -> Option<Ref<MediumLevelILFunction>> {
+ let mlil_ptr = unsafe { BNGetFunctionMediumLevelILIfAvailable(self.handle) };
+ match mlil_ptr.is_null() {
+ false => Some(unsafe { MediumLevelILFunction::ref_from_raw(mlil_ptr) }),
+ true => None,
+ }
}
- pub fn low_level_il(&self) -> Result<Ref<llil::RegularFunction<CoreArchitecture>>, ()> {
+ pub fn low_level_il(&self) -> Result<Ref<RegularLowLevelILFunction<CoreArchitecture>>, ()> {
unsafe {
- let llil = BNGetFunctionLowLevelIL(self.handle);
-
- if llil.is_null() {
- return Err(());
+ let llil_ptr = BNGetFunctionLowLevelIL(self.handle);
+ match llil_ptr.is_null() {
+ false => Ok(RegularLowLevelILFunction::ref_from_raw(
+ self.arch(),
+ llil_ptr,
+ )),
+ true => Err(()),
}
-
- Ok(llil::RegularFunction::ref_from_raw(self.arch(), llil))
}
}
pub fn low_level_il_if_available(
&self,
- ) -> Option<Ref<llil::RegularFunction<CoreArchitecture>>> {
- let llil = unsafe { BNGetFunctionLowLevelILIfAvailable(self.handle) };
- (!llil.is_null()).then(|| unsafe { llil::RegularFunction::ref_from_raw(self.arch(), llil) })
+ ) -> Option<Ref<RegularLowLevelILFunction<CoreArchitecture>>> {
+ let llil_ptr = unsafe { BNGetFunctionLowLevelILIfAvailable(self.handle) };
+ match llil_ptr.is_null() {
+ false => {
+ Some(unsafe { RegularLowLevelILFunction::ref_from_raw(self.arch(), llil_ptr) })
+ }
+ true => None,
+ }
}
- pub fn lifted_il(&self) -> Result<Ref<llil::LiftedFunction<CoreArchitecture>>, ()> {
+ pub fn lifted_il(&self) -> Result<Ref<LiftedILFunction<CoreArchitecture>>, ()> {
unsafe {
- let llil = BNGetFunctionLiftedIL(self.handle);
-
- if llil.is_null() {
- return Err(());
+ let llil_ptr = BNGetFunctionLiftedIL(self.handle);
+ match llil_ptr.is_null() {
+ false => Ok(LiftedILFunction::ref_from_raw(self.arch(), llil_ptr)),
+ true => Err(()),
}
-
- Ok(llil::LiftedFunction::ref_from_raw(self.arch(), llil))
}
}
- pub fn lifted_il_if_available(&self) -> Option<Ref<llil::LiftedFunction<CoreArchitecture>>> {
- let llil = unsafe { BNGetFunctionLiftedILIfAvailable(self.handle) };
- (!llil.is_null()).then(|| unsafe { llil::LiftedFunction::ref_from_raw(self.arch(), llil) })
+ pub fn lifted_il_if_available(&self) -> Option<Ref<LiftedILFunction<CoreArchitecture>>> {
+ let llil_ptr = unsafe { BNGetFunctionLiftedILIfAvailable(self.handle) };
+ match llil_ptr.is_null() {
+ false => Some(unsafe { LiftedILFunction::ref_from_raw(self.arch(), llil_ptr) }),
+ true => None,
+ }
}
pub fn return_type(&self) -> Conf<Ref<Type>> {
- let result = unsafe { BNGetFunctionReturnType(self.handle) };
-
- Conf::new(
- unsafe { Type::ref_from_raw(result.type_) },
- result.confidence,
- )
+ let raw_return_type = unsafe { BNGetFunctionReturnType(self.handle) };
+ Conf::<Ref<Type>>::from_owned_raw(raw_return_type)
}
pub fn set_auto_return_type<'a, C>(&self, return_type: C)
where
C: Into<Conf<&'a Type>>,
{
- let return_type: Conf<&Type> = return_type.into();
- unsafe {
- BNSetAutoFunctionReturnType(
- self.handle,
- &mut BNTypeWithConfidence {
- type_: return_type.contents.handle,
- confidence: return_type.confidence,
- },
- )
- }
+ let mut raw_return_type = Conf::<&Type>::into_raw(return_type.into());
+ unsafe { BNSetAutoFunctionReturnType(self.handle, &mut raw_return_type) }
}
pub fn set_user_return_type<'a, C>(&self, return_type: C)
where
C: Into<Conf<&'a Type>>,
{
- let return_type: Conf<&Type> = return_type.into();
- unsafe {
- BNSetUserFunctionReturnType(
- self.handle,
- &mut BNTypeWithConfidence {
- type_: return_type.contents.handle,
- confidence: return_type.confidence,
- },
- )
- }
+ let mut raw_return_type = Conf::<&Type>::into_raw(return_type.into());
+ unsafe { BNSetUserFunctionReturnType(self.handle, &mut raw_return_type) }
}
pub fn function_type(&self) -> Ref<Type> {
@@ -512,7 +594,7 @@ impl Function {
unsafe { BNSetFunctionAutoType(self.handle, t.handle) }
}
- pub fn stack_layout(&self) -> Array<NamedTypedVariable> {
+ pub fn stack_layout(&self) -> Array<NamedVariableWithType> {
let mut count = 0;
unsafe {
let variables = BNGetStackLayout(self.handle, &mut count);
@@ -547,7 +629,7 @@ impl Function {
pub fn call_stack_adjustment(&self, addr: u64, arch: Option<CoreArchitecture>) -> Conf<i64> {
let arch = arch.unwrap_or_else(|| self.arch());
- let result = unsafe { BNGetCallStackAdjustment(self.handle, arch.0, addr) };
+ let result = unsafe { BNGetCallStackAdjustment(self.handle, arch.handle, addr) };
result.into()
}
@@ -564,7 +646,7 @@ impl Function {
unsafe {
BNSetUserCallStackAdjustment(
self.handle,
- arch.0,
+ arch.handle,
addr,
adjust.contents,
adjust.confidence,
@@ -585,7 +667,7 @@ impl Function {
unsafe {
BNSetAutoCallStackAdjustment(
self.handle,
- arch.0,
+ arch.handle,
addr,
adjust.contents,
adjust.confidence,
@@ -599,9 +681,11 @@ impl Function {
arch: Option<CoreArchitecture>,
) -> Option<Conf<Ref<Type>>> {
let arch = arch.unwrap_or_else(|| self.arch());
- let result = unsafe { BNGetCallTypeAdjustment(self.handle, arch.0, addr) };
- (!result.type_.is_null())
- .then(|| unsafe { Conf::new(Type::ref_from_raw(result.type_), result.confidence) })
+ let result = unsafe { BNGetCallTypeAdjustment(self.handle, arch.handle, addr) };
+ match result.type_.is_null() {
+ false => Some(Conf::<Ref<Type>>::from_owned_raw(result)),
+ true => None,
+ }
}
/// Sets or removes the call type override at a call site to the given type.
@@ -628,8 +712,8 @@ impl Function {
let adjust_ptr = adjust_type
.as_mut()
.map(|x| x as *mut _)
- .unwrap_or(core::ptr::null_mut());
- unsafe { BNSetUserCallTypeAdjustment(self.handle, arch.0, addr, adjust_ptr) }
+ .unwrap_or(std::ptr::null_mut());
+ unsafe { BNSetUserCallTypeAdjustment(self.handle, arch.handle, addr, adjust_ptr) }
}
pub fn set_auto_call_type_adjustment<'a, I>(
@@ -645,7 +729,7 @@ impl Function {
unsafe {
BNSetAutoCallTypeAdjustment(
self.handle,
- arch.0,
+ arch.handle,
addr,
&mut BNTypeWithConfidence {
type_: adjust_type.contents.handle,
@@ -659,13 +743,13 @@ impl Function {
&self,
addr: u64,
arch: Option<CoreArchitecture>,
- ) -> Array<RegisterStackAdjustment<CoreArchitecture>> {
+ ) -> Array<RegisterStackAdjustment> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
let adjust =
- unsafe { BNGetCallRegisterStackAdjustment(self.handle, arch.0, addr, &mut count) };
+ unsafe { BNGetCallRegisterStackAdjustment(self.handle, arch.handle, addr, &mut count) };
assert!(!adjust.is_null());
- unsafe { Array::new(adjust, count, arch.handle()) }
+ unsafe { Array::new(adjust, count, ()) }
}
pub fn set_user_call_reg_stack_adjustment<I>(
@@ -674,18 +758,18 @@ impl Function {
adjust: I,
arch: Option<CoreArchitecture>,
) where
- I: IntoIterator<Item = RegisterStackAdjustment<CoreArchitecture>>,
+ I: IntoIterator<Item = RegisterStackAdjustment>,
{
let arch = arch.unwrap_or_else(|| self.arch());
- let mut adjust_buf: Box<[BNRegisterStackAdjustment]> =
- adjust.into_iter().map(|adjust| adjust.into_raw()).collect();
+ let adjustments: Vec<BNRegisterStackAdjustment> =
+ adjust.into_iter().map(Into::into).collect();
unsafe {
BNSetUserCallRegisterStackAdjustment(
self.handle,
- arch.0,
+ arch.handle,
addr,
- adjust_buf.as_mut_ptr(),
- adjust_buf.len(),
+ adjustments.as_ptr() as *mut _,
+ adjustments.len(),
)
}
}
@@ -696,19 +780,18 @@ impl Function {
adjust: I,
arch: Option<CoreArchitecture>,
) where
- I: IntoIterator<Item = RegisterStackAdjustment<CoreArchitecture>>,
+ I: IntoIterator<Item = RegisterStackAdjustment>,
{
let arch = arch.unwrap_or_else(|| self.arch());
- let mut adjust_buf: Box<[BNRegisterStackAdjustment]> =
- adjust.into_iter().map(|reg| reg.into_raw()).collect();
-
+ let adjustments: Vec<BNRegisterStackAdjustment> =
+ adjust.into_iter().map(Into::into).collect();
unsafe {
BNSetAutoCallRegisterStackAdjustment(
self.handle,
- arch.0,
+ arch.handle,
addr,
- adjust_buf.as_mut_ptr(),
- adjust_buf.len(),
+ adjustments.as_ptr() as *mut _,
+ adjustments.len(),
)
}
}
@@ -718,17 +801,17 @@ impl Function {
addr: u64,
reg_stack_id: u32,
arch: Option<CoreArchitecture>,
- ) -> RegisterStackAdjustment<CoreArchitecture> {
+ ) -> RegisterStackAdjustment {
let arch = arch.unwrap_or_else(|| self.arch());
let adjust = unsafe {
BNGetCallRegisterStackAdjustmentForRegisterStack(
self.handle,
- arch.0,
+ arch.handle,
addr,
reg_stack_id,
)
};
- unsafe { RegisterStackAdjustment::from_raw(adjust, arch) }
+ RegisterStackAdjustment::from(adjust)
}
pub fn set_user_call_reg_stack_adjustment_for_reg_stack<I>(
@@ -745,7 +828,7 @@ impl Function {
unsafe {
BNSetUserCallRegisterStackAdjustmentForRegisterStack(
self.handle,
- arch.0,
+ arch.handle,
addr,
reg_stack_id,
adjust.contents,
@@ -768,7 +851,7 @@ impl Function {
unsafe {
BNSetAutoCallRegisterStackAdjustmentForRegisterStack(
self.handle,
- arch.0,
+ arch.handle,
addr,
reg_stack_id,
adjust.contents,
@@ -777,45 +860,42 @@ impl Function {
}
}
- pub fn reg_stack_adjustments(&self) -> Array<RegisterStackAdjustment<CoreArchitecture>> {
+ pub fn reg_stack_adjustments(&self) -> Array<RegisterStackAdjustment> {
let mut count = 0;
let adjust = unsafe { BNGetFunctionRegisterStackAdjustments(self.handle, &mut count) };
assert!(!adjust.is_null());
- unsafe { Array::new(adjust, count, self.arch().handle()) }
+ unsafe { Array::new(adjust, count, ()) }
}
- pub fn set_user_reg_stack_adjustments<I, A>(&self, values: I)
+ pub fn set_user_reg_stack_adjustments<I>(&self, values: I)
where
- I: IntoIterator<Item = RegisterStackAdjustment<A>>,
- A: Architecture,
+ I: IntoIterator<Item = RegisterStackAdjustment>,
{
- let mut values: Box<[BNRegisterStackAdjustment]> =
- values.into_iter().map(|r| r.into_raw()).collect();
+ let values: Vec<BNRegisterStackAdjustment> = values.into_iter().map(Into::into).collect();
unsafe {
BNSetUserFunctionRegisterStackAdjustments(
self.handle,
- values.as_mut_ptr(),
+ values.as_ptr() as *mut _,
values.len(),
)
}
}
- pub fn set_auto_reg_stack_adjustments<I, A>(&self, values: I)
+ pub fn set_auto_reg_stack_adjustments<I>(&self, values: I)
where
- I: IntoIterator<Item = RegisterStackAdjustment<A>>,
- A: Architecture,
+ I: IntoIterator<Item = RegisterStackAdjustment>,
{
- let mut values: Box<[BNRegisterStackAdjustment]> =
- values.into_iter().map(|r| r.into_raw()).collect();
+ let values: Vec<BNRegisterStackAdjustment> = values.into_iter().map(Into::into).collect();
unsafe {
BNSetAutoFunctionRegisterStackAdjustments(
self.handle,
- values.as_mut_ptr(),
+ values.as_ptr() as *mut _,
values.len(),
)
}
}
+ // TODO: Turn this into an actual type?
/// List of function variables: including name, variable and type
pub fn variables(&self) -> Array<(&str, Variable, &Type)> {
let mut count = 0;
@@ -833,17 +913,12 @@ impl Function {
pub fn parameter_variables(&self) -> Conf<Vec<Variable>> {
unsafe {
- let mut variables = BNGetFunctionParameterVariables(self.handle);
- let mut result = Vec::with_capacity(variables.count);
- let confidence = variables.confidence;
- let vars = std::slice::from_raw_parts(variables.vars, variables.count);
-
- for var in vars.iter().take(variables.count) {
- result.push(Variable::from_raw(*var));
- }
-
- BNFreeParameterVariables(&mut variables);
- Conf::new(result, confidence)
+ let mut raw_variables = BNGetFunctionParameterVariables(self.handle);
+ let raw_var_list = std::slice::from_raw_parts(raw_variables.vars, raw_variables.count);
+ let variables: Vec<Variable> = raw_var_list.iter().map(Into::into).collect();
+ let confidence = raw_variables.confidence;
+ BNFreeParameterVariables(&mut raw_variables);
+ Conf::new(variables, confidence)
}
}
@@ -851,12 +926,12 @@ impl Function {
where
I: IntoIterator<Item = Variable>,
{
- let mut vars: Box<[BNVariable]> = values.into_iter().map(|var| var.raw()).collect();
+ let vars: Vec<BNVariable> = values.into_iter().map(Into::into).collect();
unsafe {
BNSetUserFunctionParameterVariables(
self.handle,
&mut BNParameterVariablesWithConfidence {
- vars: vars.as_mut_ptr(),
+ vars: vars.as_ptr() as *mut _,
count: vars.len(),
confidence,
},
@@ -868,12 +943,12 @@ impl Function {
where
I: IntoIterator<Item = Variable>,
{
- let mut vars: Box<[BNVariable]> = values.into_iter().map(|var| var.raw()).collect();
+ let vars: Vec<BNVariable> = values.into_iter().map(Into::into).collect();
unsafe {
BNSetAutoFunctionParameterVariables(
self.handle,
&mut BNParameterVariablesWithConfidence {
- vars: vars.as_mut_ptr(),
+ vars: vars.as_ptr() as *mut _,
count: vars.len(),
confidence,
},
@@ -889,9 +964,10 @@ impl Function {
arch: Option<CoreArchitecture>,
) -> RegisterValue {
let arch = arch.unwrap_or_else(|| self.arch());
- let func_type = func_type.map(|f| f.handle).unwrap_or(core::ptr::null_mut());
- let value =
- unsafe { BNGetParameterValueAtInstruction(self.handle, arch.0, addr, func_type, i) };
+ let func_type = func_type.map(|f| f.handle).unwrap_or(std::ptr::null_mut());
+ let value = unsafe {
+ BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i)
+ };
value.into()
}
@@ -912,11 +988,7 @@ impl Function {
BNApplyImportedTypes(
self.handle,
sym.handle,
- if let Some(t) = t {
- t.handle
- } else {
- core::ptr::null_mut()
- },
+ t.map(|t| t.handle).unwrap_or(std::ptr::null_mut()),
);
}
}
@@ -972,15 +1044,7 @@ impl Function {
C: Into<Conf<bool>>,
{
let value: Conf<bool> = value.into();
- unsafe {
- BNSetAutoFunctionInlinedDuringAnalysis(
- self.handle,
- BNBoolWithConfidence {
- value: value.contents,
- confidence: value.confidence,
- },
- )
- }
+ unsafe { BNSetAutoFunctionInlinedDuringAnalysis(self.handle, value.into()) }
}
pub fn set_user_inline_during_analysis<C>(&self, value: C)
@@ -988,15 +1052,7 @@ impl Function {
C: Into<Conf<bool>>,
{
let value: Conf<bool> = value.into();
- unsafe {
- BNSetUserFunctionInlinedDuringAnalysis(
- self.handle,
- BNBoolWithConfidence {
- value: value.contents,
- confidence: value.confidence,
- },
- )
- }
+ unsafe { BNSetUserFunctionInlinedDuringAnalysis(self.handle, value.into()) }
}
pub fn analysis_performance_info(&self) -> Array<PerformanceInfo> {
@@ -1024,12 +1080,18 @@ impl Function {
/// # Example
///
/// ```no_run
- /// # use binaryninja::binaryview::{BinaryView, BinaryViewExt};
+ /// # use binaryninja::binary_view::{BinaryView, BinaryViewExt};
/// # use binaryninja::function::Function;
/// # let fun: Function = todo!();
/// # let bv: BinaryView = todo!();
/// let important = bv.create_tag_type("Important", "⚠️");
- /// fun.add_tag(&important, "I think this is the main function", None, false, None);
+ /// fun.add_tag(
+ /// &important,
+ /// "I think this is the main function",
+ /// None,
+ /// false,
+ /// None,
+ /// );
/// let crash = bv.create_tag_type("Crashes", "🎯");
/// fun.add_tag(&crash, "Nullpointer dereference", Some(0x1337), false, None);
/// ```
@@ -1045,15 +1107,19 @@ impl Function {
// Create tag
let tag = Tag::new(tag_type, data);
- let binaryview = unsafe { BinaryView::from_raw(BNGetFunctionData(self.handle)) };
+ let binaryview = unsafe { BinaryView::ref_from_raw(BNGetFunctionData(self.handle)) };
unsafe { BNAddTag(binaryview.handle, tag.handle, user) };
unsafe {
match (user, addr) {
(false, None) => BNAddAutoFunctionTag(self.handle, tag.handle),
- (false, Some(addr)) => BNAddAutoAddressTag(self.handle, arch.0, addr, tag.handle),
+ (false, Some(addr)) => {
+ BNAddAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
+ }
(true, None) => BNAddUserFunctionTag(self.handle, tag.handle),
- (true, Some(addr)) => BNAddUserAddressTag(self.handle, arch.0, addr, tag.handle),
+ (true, Some(addr)) => {
+ BNAddUserAddressTag(self.handle, arch.handle, addr, tag.handle)
+ }
}
}
}
@@ -1075,10 +1141,12 @@ impl Function {
match (user, addr) {
(false, None) => BNRemoveAutoFunctionTag(self.handle, tag.handle),
(false, Some(addr)) => {
- BNRemoveAutoAddressTag(self.handle, arch.0, addr, tag.handle)
+ BNRemoveAutoAddressTag(self.handle, arch.handle, addr, tag.handle)
}
(true, None) => BNRemoveUserFunctionTag(self.handle, tag.handle),
- (true, Some(addr)) => BNRemoveUserAddressTag(self.handle, arch.0, addr, tag.handle),
+ (true, Some(addr)) => {
+ BNRemoveUserAddressTag(self.handle, arch.handle, addr, tag.handle)
+ }
}
}
}
@@ -1101,11 +1169,11 @@ impl Function {
match (user, addr) {
(false, None) => BNRemoveAutoFunctionTagsOfType(self.handle, tag_type.handle),
(false, Some(addr)) => {
- BNRemoveAutoAddressTagsOfType(self.handle, arch.0, addr, tag_type.handle)
+ BNRemoveAutoAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle)
}
(true, None) => BNRemoveUserFunctionTagsOfType(self.handle, tag_type.handle),
(true, Some(addr)) => {
- BNRemoveUserAddressTagsOfType(self.handle, arch.0, addr, tag_type.handle)
+ BNRemoveUserAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle)
}
}
}
@@ -1129,7 +1197,7 @@ impl Function {
/// ```
pub fn add_user_code_ref(&self, from_addr: u64, to_addr: u64, arch: Option<CoreArchitecture>) {
let arch = arch.unwrap_or_else(|| self.arch());
- unsafe { BNAddUserCodeReference(self.handle, arch.0, from_addr, to_addr) }
+ unsafe { BNAddUserCodeReference(self.handle, arch.handle, from_addr, to_addr) }
}
/// Removes a user-defined cross-reference.
@@ -1154,7 +1222,7 @@ impl Function {
arch: Option<CoreArchitecture>,
) {
let arch = arch.unwrap_or_else(|| self.arch());
- unsafe { BNRemoveUserCodeReference(self.handle, arch.0, from_addr, to_addr) }
+ unsafe { BNRemoveUserCodeReference(self.handle, arch.handle, from_addr, to_addr) }
}
/// Places a user-defined type cross-reference from the instruction at
@@ -1170,17 +1238,18 @@ impl Function {
/// ```no_run
/// # use binaryninja::function::Function;
/// # let fun: Function = todo!();
- /// fun.add_user_type_ref(0x1337, &"A".into(), None);
+ /// fun.add_user_type_ref(0x1337, "A", None);
/// ```
- pub fn add_user_type_ref(
+ pub fn add_user_type_ref<T: Into<QualifiedName>>(
&self,
from_addr: u64,
- name: &QualifiedName,
+ name: T,
arch: Option<CoreArchitecture>,
) {
let arch = arch.unwrap_or_else(|| self.arch());
- let name_ptr = &name.0 as *const BNQualifiedName as *mut _;
- unsafe { BNAddUserTypeReference(self.handle, arch.0, from_addr, name_ptr) }
+ let mut raw_name = QualifiedName::into_raw(name.into());
+ unsafe { BNAddUserTypeReference(self.handle, arch.handle, from_addr, &mut raw_name) };
+ QualifiedName::free_raw(raw_name);
}
/// Removes a user-defined type cross-reference.
@@ -1195,17 +1264,18 @@ impl Function {
/// ```no_run
/// # use binaryninja::function::Function;
/// # let fun: Function = todo!();
- /// fun.remove_user_type_ref(0x1337, &"A".into(), None);
+ /// fun.remove_user_type_ref(0x1337, "A", None);
/// ```
- pub fn remove_user_type_ref(
+ pub fn remove_user_type_ref<T: Into<QualifiedName>>(
&self,
from_addr: u64,
- name: &QualifiedName,
+ name: T,
arch: Option<CoreArchitecture>,
) {
let arch = arch.unwrap_or_else(|| self.arch());
- let name_ptr = &name.0 as *const BNQualifiedName as *mut _;
- unsafe { BNRemoveUserTypeReference(self.handle, arch.0, from_addr, name_ptr) }
+ let mut raw_name = QualifiedName::into_raw(name.into());
+ unsafe { BNRemoveUserTypeReference(self.handle, arch.handle, from_addr, &mut raw_name) };
+ QualifiedName::free_raw(raw_name);
}
/// Places a user-defined type field cross-reference from the
@@ -1223,22 +1293,30 @@ impl Function {
/// ```no_run
/// # use binaryninja::function::Function;
/// # let fun: Function = todo!();
- /// fun.add_user_type_field_ref(0x1337, &"A".into(), 0x8, None, None);
+ /// fun.add_user_type_field_ref(0x1337, "A", 0x8, None, None);
/// ```
- pub fn add_user_type_field_ref(
+ pub fn add_user_type_field_ref<T: Into<QualifiedName>>(
&self,
from_addr: u64,
- name: &QualifiedName,
+ name: T,
offset: u64,
arch: Option<CoreArchitecture>,
size: Option<usize>,
) {
let size = size.unwrap_or(0);
let arch = arch.unwrap_or_else(|| self.arch());
- let name_ptr = &name.0 as *const _ as *mut _;
+ let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
- BNAddUserTypeFieldReference(self.handle, arch.0, from_addr, name_ptr, offset, size)
- }
+ BNAddUserTypeFieldReference(
+ self.handle,
+ arch.handle,
+ from_addr,
+ &mut raw_name,
+ offset,
+ size,
+ )
+ };
+ QualifiedName::free_raw(raw_name);
}
/// Removes a user-defined type field cross-reference.
@@ -1255,22 +1333,30 @@ impl Function {
/// ```no_run
/// # use binaryninja::function::Function;
/// # let fun: Function = todo!();
- /// fun.remove_user_type_field_ref(0x1337, &"A".into(), 0x8, None, None);
+ /// fun.remove_user_type_field_ref(0x1337, "A", 0x8, None, None);
/// ```
- pub fn remove_user_type_field_ref(
+ pub fn remove_user_type_field_ref<T: Into<QualifiedName>>(
&self,
from_addr: u64,
- name: &QualifiedName,
+ name: T,
offset: u64,
arch: Option<CoreArchitecture>,
size: Option<usize>,
) {
let size = size.unwrap_or(0);
let arch = arch.unwrap_or_else(|| self.arch());
- let name_ptr = &name.0 as *const _ as *mut _;
+ let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
- BNRemoveUserTypeFieldReference(self.handle, arch.0, from_addr, name_ptr, offset, size)
+ BNRemoveUserTypeFieldReference(
+ self.handle,
+ arch.handle,
+ from_addr,
+ &mut raw_name,
+ offset,
+ size,
+ )
}
+ QualifiedName::free_raw(raw_name);
}
pub fn constant_data(
@@ -1280,9 +1366,11 @@ impl Function {
size: Option<usize>,
) -> (DataBuffer, BuiltinType) {
let size = size.unwrap_or(0);
- let state_raw = state.into_raw_value();
+ // TODO: Adjust `BuiltinType`?
let mut builtin_type = BuiltinType::BuiltinNone;
- let buffer = DataBuffer::from_raw(unsafe { BNGetConstantData(self.handle, state_raw, value, size, &mut builtin_type) });
+ let buffer = DataBuffer::from_raw(unsafe {
+ BNGetConstantData(self.handle, state, value, size, &mut builtin_type)
+ });
(buffer, builtin_type)
}
@@ -1293,8 +1381,9 @@ impl Function {
) -> Array<ConstantReference> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
- let refs =
- unsafe { BNGetConstantsReferencedByInstruction(self.handle, arch.0, addr, &mut count) };
+ let refs = unsafe {
+ BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, &mut count)
+ };
assert!(!refs.is_null());
unsafe { Array::new(refs, count, ()) }
}
@@ -1307,7 +1396,12 @@ impl Function {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
let refs = unsafe {
- BNGetConstantsReferencedByInstructionIfAvailable(self.handle, arch.0, addr, &mut count)
+ BNGetConstantsReferencedByInstructionIfAvailable(
+ self.handle,
+ arch.handle,
+ addr,
+ &mut count,
+ )
};
assert!(!refs.is_null());
unsafe { Array::new(refs, count, ()) }
@@ -1320,12 +1414,12 @@ impl Function {
pub fn function_tags(&self, auto: Option<bool>, tag_type: Option<&str>) -> Array<Tag> {
let mut count = 0;
- let tag_type = tag_type.map(|tag_type| self.view().get_tag_type(tag_type));
+ let tag_type = tag_type.map(|tag_type| self.view().tag_type_by_name(tag_type));
let tags = unsafe {
match (tag_type, auto) {
// received a tag_type, BinaryView found none
- (Some(None), _) => return Array::new(core::ptr::null_mut(), 0, ()),
+ (Some(None), _) => return Array::new(std::ptr::null_mut(), 0, ()),
// with tag_type
(Some(Some(tag_type)), None) => {
@@ -1368,9 +1462,13 @@ impl Function {
let mut count = 0;
let tags = match auto {
- None => unsafe { BNGetAddressTags(self.handle, arch.0, addr, &mut count) },
- Some(true) => unsafe { BNGetAutoAddressTags(self.handle, arch.0, addr, &mut count) },
- Some(false) => unsafe { BNGetUserAddressTags(self.handle, arch.0, addr, &mut count) },
+ None => unsafe { BNGetAddressTags(self.handle, arch.handle, addr, &mut count) },
+ Some(true) => unsafe {
+ BNGetAutoAddressTags(self.handle, arch.handle, addr, &mut count)
+ },
+ Some(false) => unsafe {
+ BNGetUserAddressTags(self.handle, arch.handle, addr, &mut count)
+ },
};
assert!(!tags.is_null());
unsafe { Array::new(tags, count, ()) }
@@ -1391,13 +1489,31 @@ impl Function {
let tags = match auto {
None => unsafe {
- BNGetAddressTagsInRange(self.handle, arch.0, range.start, range.end, &mut count)
+ BNGetAddressTagsInRange(
+ self.handle,
+ arch.handle,
+ range.start,
+ range.end,
+ &mut count,
+ )
},
Some(true) => unsafe {
- BNGetAutoAddressTagsInRange(self.handle, arch.0, range.start, range.end, &mut count)
+ BNGetAutoAddressTagsInRange(
+ self.handle,
+ arch.handle,
+ range.start,
+ range.end,
+ &mut count,
+ )
},
Some(false) => unsafe {
- BNGetUserAddressTagsInRange(self.handle, arch.0, range.start, range.end, &mut count)
+ BNGetUserAddressTagsInRange(
+ self.handle,
+ arch.handle,
+ range.start,
+ range.end,
+ &mut count,
+ )
},
};
assert!(!tags.is_null());
@@ -1425,13 +1541,13 @@ impl Function {
.into_iter()
.map(|address| BNArchitectureAndAddress {
address,
- arch: arch.0,
+ arch: arch.handle,
})
.collect();
unsafe {
BNSetUserIndirectBranches(
self.handle,
- arch.0,
+ arch.handle,
source,
branches.as_mut_ptr(),
branches.len(),
@@ -1452,13 +1568,13 @@ impl Function {
.into_iter()
.map(|address| BNArchitectureAndAddress {
address,
- arch: arch.0,
+ arch: arch.handle,
})
.collect();
unsafe {
BNSetAutoIndirectBranches(
self.handle,
- arch.0,
+ arch.handle,
source,
branches.as_mut_ptr(),
branches.len(),
@@ -1474,7 +1590,8 @@ impl Function {
) -> Array<IndirectBranchInfo> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
- let branches = unsafe { BNGetIndirectBranchesAt(self.handle, arch.0, addr, &mut count) };
+ let branches =
+ unsafe { BNGetIndirectBranchesAt(self.handle, arch.handle, addr, &mut count) };
assert!(!branches.is_null());
unsafe { Array::new(branches, count, ()) }
}
@@ -1486,8 +1603,8 @@ impl Function {
/// ```
pub fn instr_highlight(&self, addr: u64, arch: Option<CoreArchitecture>) -> HighlightColor {
let arch = arch.unwrap_or_else(|| self.arch());
- let color = unsafe { BNGetInstructionHighlight(self.handle, arch.0, addr) };
- HighlightColor::from_raw(color)
+ let color = unsafe { BNGetInstructionHighlight(self.handle, arch.handle, addr) };
+ HighlightColor::from(color)
}
/// Sets the highlights the instruction at the specified address with the supplied color
@@ -1504,22 +1621,24 @@ impl Function {
arch: Option<CoreArchitecture>,
) {
let arch = arch.unwrap_or_else(|| self.arch());
- let color_raw = color.into_raw();
- unsafe { BNSetAutoInstructionHighlight(self.handle, arch.0, addr, color_raw) }
+ unsafe { BNSetAutoInstructionHighlight(self.handle, arch.handle, addr, color.into()) }
}
/// Sets the highlights the instruction at the specified address with the supplied color
///
/// * `addr` - virtual address of the instruction to be highlighted
/// * `color` - Color value to use for highlighting
- /// * `arch` - (optional) Architecture of the instruction if different from self.arch
+ /// * `arch` - (optional) Architecture of the instruction, pass this if not views default arch
///
/// # Example
/// ```no_run
- /// # use binaryninja::types::HighlightColor;
- /// # let fun: binaryninja::function::Function = todo!();
- /// let color = HighlightColor::NoHighlightColor { alpha: u8::MAX };
- /// fun.set_user_instr_highlight(0x1337, color, None);
+ /// # use binaryninja::function::{HighlightColor, HighlightStandardColor};
+ /// # let function: binaryninja::function::Function = todo!();
+ /// let color = HighlightColor::StandardHighlightColor {
+ /// color: HighlightStandardColor::RedHighlightColor,
+ /// alpha: u8::MAX,
+ /// };
+ /// function.set_user_instr_highlight(0x1337, color, None);
/// ```
pub fn set_user_instr_highlight(
&self,
@@ -1528,8 +1647,7 @@ impl Function {
arch: Option<CoreArchitecture>,
) {
let arch = arch.unwrap_or_else(|| self.arch());
- let color_raw = color.into_raw();
- unsafe { BNSetUserInstructionHighlight(self.handle, arch.0, addr, color_raw) }
+ unsafe { BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color.into()) }
}
/// return the address, if any, of the instruction that contains the
@@ -1541,7 +1659,7 @@ impl Function {
) -> Option<u64> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut start = 0;
- unsafe { BNGetInstructionContainingAddress(self.handle, arch.0, addr, &mut start) }
+ unsafe { BNGetInstructionContainingAddress(self.handle, arch.handle, addr, &mut start) }
.then_some(start)
}
@@ -1561,7 +1679,9 @@ impl Function {
arch: Option<CoreArchitecture>,
) -> IntegerDisplayType {
let arch = arch.unwrap_or_else(|| self.arch());
- unsafe { BNGetIntegerConstantDisplayType(self.handle, arch.0, instr_addr, value, operand) }
+ unsafe {
+ BNGetIntegerConstantDisplayType(self.handle, arch.handle, instr_addr, value, operand)
+ }
}
/// Change the text display type for an integer token in the disassembly or IL views
@@ -1585,11 +1705,11 @@ impl Function {
let enum_display_typeid = enum_display_typeid.map(BnStrCompatible::into_bytes_with_nul);
let enum_display_typeid_ptr = enum_display_typeid
.map(|x| x.as_ref().as_ptr() as *const c_char)
- .unwrap_or(core::ptr::null());
+ .unwrap_or(std::ptr::null());
unsafe {
BNSetIntegerConstantDisplayType(
self.handle,
- arch.0,
+ arch.handle,
instr_addr,
value,
operand,
@@ -1618,7 +1738,7 @@ impl Function {
unsafe {
BnString::from_raw(BNGetIntegerConstantDisplayTypeEnumerationType(
self.handle,
- arch.0,
+ arch.handle,
instr_addr,
value,
operand,
@@ -1661,11 +1781,12 @@ impl Function {
pub fn register_value_at(
&self,
addr: u64,
- reg: u32,
+ reg: RegisterId,
arch: Option<CoreArchitecture>,
) -> RegisterValue {
let arch = arch.unwrap_or_else(|| self.arch());
- let register = unsafe { BNGetRegisterValueAtInstruction(self.handle, arch.0, addr, reg) };
+ let register =
+ unsafe { BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg.0) };
register.into()
}
@@ -1685,12 +1806,12 @@ impl Function {
pub fn register_value_after(
&self,
addr: u64,
- reg: u32,
+ reg: RegisterId,
arch: Option<CoreArchitecture>,
) -> RegisterValue {
let arch = arch.unwrap_or_else(|| self.arch());
let register =
- unsafe { BNGetRegisterValueAfterInstruction(self.handle, arch.0, addr, reg) };
+ unsafe { BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg.0) };
register.into()
}
@@ -1707,7 +1828,7 @@ impl Function {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
let regs =
- unsafe { BNGetRegistersReadByInstruction(self.handle, arch.0, addr, &mut count) };
+ unsafe { BNGetRegistersReadByInstruction(self.handle, arch.handle, addr, &mut count) };
assert!(!regs.is_null());
unsafe { Array::new(regs, count, arch) }
}
@@ -1719,8 +1840,9 @@ impl Function {
) -> Array<CoreRegister> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
- let regs =
- unsafe { BNGetRegistersWrittenByInstruction(self.handle, arch.0, addr, &mut count) };
+ let regs = unsafe {
+ BNGetRegistersWrittenByInstruction(self.handle, arch.handle, addr, &mut count)
+ };
assert!(!regs.is_null());
unsafe { Array::new(regs, count, arch) }
}
@@ -1737,7 +1859,7 @@ impl Function {
where
I: IntoIterator<Item = CoreRegister>,
{
- let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id()).collect();
+ let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id().0).collect();
let mut regs = BNRegisterSetWithConfidence {
regs: regs.as_mut_ptr(),
count: regs.len(),
@@ -1750,7 +1872,7 @@ impl Function {
where
I: IntoIterator<Item = CoreRegister>,
{
- let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id()).collect();
+ let mut regs: Box<[u32]> = registers.into_iter().map(|reg| reg.id().0).collect();
let mut regs = BNRegisterSetWithConfidence {
regs: regs.as_mut_ptr(),
count: regs.len(),
@@ -1767,8 +1889,9 @@ impl Function {
arch: Option<CoreArchitecture>,
) -> RegisterValue {
let arch = arch.unwrap_or_else(|| self.arch());
- let value =
- unsafe { BNGetStackContentsAtInstruction(self.handle, arch.0, addr, offset, size) };
+ let value = unsafe {
+ BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size)
+ };
value.into()
}
@@ -1780,8 +1903,9 @@ impl Function {
arch: Option<CoreArchitecture>,
) -> RegisterValue {
let arch = arch.unwrap_or_else(|| self.arch());
- let value =
- unsafe { BNGetStackContentsAfterInstruction(self.handle, arch.0, addr, offset, size) };
+ let value = unsafe {
+ BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size)
+ };
value.into()
}
@@ -1792,14 +1916,20 @@ impl Function {
arch: Option<CoreArchitecture>,
) -> Option<(Variable, BnString, Conf<Ref<Type>>)> {
let arch = arch.unwrap_or_else(|| self.arch());
- let mut found_value: BNVariableNameAndType = unsafe { mem::zeroed() };
+ let mut found_value = BNVariableNameAndType::default();
let found = unsafe {
- BNGetStackVariableAtFrameOffset(self.handle, arch.0, addr, offset, &mut found_value)
+ BNGetStackVariableAtFrameOffset(
+ self.handle,
+ arch.handle,
+ addr,
+ offset,
+ &mut found_value,
+ )
};
if !found {
return None;
}
- let var = unsafe { Variable::from_raw(found_value.var) };
+ let var = Variable::from(found_value.var);
let name = unsafe { BnString::from_raw(found_value.name) };
let var_type = Conf::new(
unsafe { Type::ref_from_raw(found_value.type_) },
@@ -1816,7 +1946,7 @@ impl Function {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
let refs = unsafe {
- BNGetStackVariablesReferencedByInstruction(self.handle, arch.0, addr, &mut count)
+ BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, &mut count)
};
assert!(!refs.is_null());
unsafe { Array::new(refs, count, ()) }
@@ -1832,7 +1962,7 @@ impl Function {
let refs = unsafe {
BNGetStackVariablesReferencedByInstructionIfAvailable(
self.handle,
- arch.0,
+ arch.handle,
addr,
&mut count,
)
@@ -1851,7 +1981,7 @@ impl Function {
&self,
settings: Option<&DisassemblySettings>,
) -> Array<DisassemblyTextLine> {
- let settings = settings.map(|s| s.handle).unwrap_or(core::ptr::null_mut());
+ let settings = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
let mut count = 0;
let lines = unsafe { BNGetFunctionTypeTokens(self.handle, settings, &mut count) };
assert!(!lines.is_null());
@@ -1860,11 +1990,12 @@ impl Function {
pub fn is_call_instruction(&self, addr: u64, arch: Option<CoreArchitecture>) -> bool {
let arch = arch.unwrap_or_else(|| self.arch());
- unsafe { BNIsCallInstruction(self.handle, arch.0, addr) }
+ unsafe { BNIsCallInstruction(self.handle, arch.handle, addr) }
}
pub fn is_variable_user_defined(&self, var: &Variable) -> bool {
- unsafe { BNIsVariableUserDefined(self.handle, &var.raw()) }
+ let raw_var = BNVariable::from(var);
+ unsafe { BNIsVariableUserDefined(self.handle, &raw_var) }
}
pub fn is_pure(&self) -> Conf<bool> {
@@ -1906,7 +2037,7 @@ impl Function {
/// Indicates that callers of this function need to be reanalyzed during the next update cycle
///
- /// * `uppdate_type` - Desired update type
+ /// * `update_type` - Desired update type
pub fn mark_caller_updates_required(&self, update_type: FunctionUpdateType) {
unsafe { BNMarkCallerUpdatesRequired(self.handle, update_type) }
}
@@ -1923,7 +2054,7 @@ impl Function {
unsafe { Array::new(vars, count, ()) }
}
- /// Merge one or more varibles in `sources` into the `target` variable. All
+ /// Merge one or more variables in `sources` into the `target` variable. All
/// variable accesses to the variables in `sources` will be rewritten to use `target`.
///
/// * `target` - target variable
@@ -1933,11 +2064,12 @@ impl Function {
target: &Variable,
sources: impl IntoIterator<Item = &'a Variable>,
) {
- let sources_raw: Box<[BNVariable]> = sources.into_iter().map(|s| s.raw()).collect();
+ let raw_target_var = BNVariable::from(target);
+ let sources_raw: Vec<BNVariable> = sources.into_iter().copied().map(Into::into).collect();
unsafe {
BNMergeVariables(
self.handle,
- &target.raw(),
+ &raw_target_var,
sources_raw.as_ptr(),
sources_raw.len(),
)
@@ -1954,20 +2086,21 @@ impl Function {
target: &Variable,
sources: impl IntoIterator<Item = &'a Variable>,
) {
- let sources_raw: Box<[BNVariable]> = sources.into_iter().map(|s| s.raw()).collect();
+ let raw_target_var = BNVariable::from(target);
+ let sources_raw: Vec<BNVariable> = sources.into_iter().copied().map(Into::into).collect();
unsafe {
BNUnmergeVariables(
self.handle,
- &target.raw(),
+ &raw_target_var,
sources_raw.as_ptr(),
sources_raw.len(),
)
}
}
- /// Splits a varible at the definition site. The given `var` must be the
+ /// Splits a variable at the definition site. The given `var` must be the
/// variable unique to the definition and should be obtained by using
- /// [mlil::MediumLevelILInstruction::get_split_var_for_definition] at the definition site.
+ /// [crate::medium_level_il::MediumLevelILInstruction::get_split_var_for_definition] at the definition site.
///
/// This function is not meant to split variables that have been previously merged. Use
/// [Function::unmerge_variables] to split previously merged variables.
@@ -1984,16 +2117,18 @@ impl Function {
///
/// * `var` - variable to split
pub fn split_variable(&self, var: &Variable) {
- unsafe { BNSplitVariable(self.handle, &var.raw()) }
+ let raw_var = BNVariable::from(var);
+ unsafe { BNSplitVariable(self.handle, &raw_var) }
}
- /// Undoes varible splitting performed with [Function::split_variable]. The given `var`
+ /// Undoes variable splitting performed with [Function::split_variable]. The given `var`
/// must be the variable unique to the definition and should be obtained by using
- /// [mlil::MediumLevelILInstruction::get_split_var_for_definition] at the definition site.
+ /// [crate::medium_level_il::MediumLevelILInstruction::get_split_var_for_definition] at the definition site.
///
/// * `var` - variable to unsplit
pub fn unsplit_variable(&self, var: &Variable) {
- unsafe { BNUnsplitVariable(self.handle, &var.raw()) }
+ let raw_var = BNVariable::from(var);
+ unsafe { BNUnsplitVariable(self.handle, &raw_var) }
}
/// Causes this function to be reanalyzed. This function does not wait for the analysis to finish.
@@ -2043,7 +2178,7 @@ impl Function {
/// 'user' functions may or may not have been created by a user through the or API. For instance the entry point
/// into a function is always created a 'user' function. 'user' functions should be considered the root of auto
/// analysis.
- pub fn auto(&self) -> bool {
+ pub fn is_auto(&self) -> bool {
unsafe { BNWasFunctionAutomaticallyDiscovered(self.handle) }
}
@@ -2061,15 +2196,15 @@ impl Function {
/// Returns a list of ReferenceSource objects corresponding to the addresses
/// in functions which reference this function
pub fn caller_sites(&self) -> Array<CodeReference> {
- self.view().get_code_refs(self.start())
+ self.view().code_refs_to_addr(self.start())
}
/// Calling convention used by the function
- pub fn calling_convention(&self) -> Option<Conf<Ref<CallingConvention<CoreArchitecture>>>> {
+ pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
let result = unsafe { BNGetFunctionCallingConvention(self.handle) };
(!result.convention.is_null()).then(|| {
Conf::new(
- unsafe { CallingConvention::ref_from_raw(result.convention, self.arch()) },
+ unsafe { CoreCallingConvention::ref_from_raw(result.convention, self.arch()) },
result.confidence,
)
})
@@ -2078,9 +2213,9 @@ impl Function {
/// Set the User calling convention used by the function
pub fn set_user_calling_convention<'a, I>(&self, value: Option<I>)
where
- I: Into<Conf<&'a CallingConvention<CoreArchitecture>>>,
+ I: Into<Conf<&'a CoreCallingConvention>>,
{
- let mut conv_conf: BNCallingConventionWithConfidence = unsafe { mem::zeroed() };
+ let mut conv_conf = BNCallingConventionWithConfidence::default();
if let Some(value) = value {
let value = value.into();
conv_conf.convention = value.contents.handle;
@@ -2092,9 +2227,9 @@ impl Function {
/// Set the calling convention used by the function
pub fn set_auto_calling_convention<'a, I>(&self, value: Option<I>)
where
- I: Into<Conf<&'a CallingConvention<CoreArchitecture>>>,
+ I: Into<Conf<&'a CoreCallingConvention>>,
{
- let mut conv_conf: BNCallingConventionWithConfidence = unsafe { mem::zeroed() };
+ let mut conv_conf = BNCallingConventionWithConfidence::default();
if let Some(value) = value {
let value = value.into();
conv_conf.convention = value.contents.handle;
@@ -2186,7 +2321,7 @@ impl Function {
where
I: IntoIterator<Item = CoreRegister>,
{
- let mut regs: Box<[u32]> = values.into_iter().map(|reg| reg.id()).collect();
+ let mut regs: Box<[u32]> = values.into_iter().map(|reg| reg.id().0).collect();
let mut regs = BNRegisterSetWithConfidence {
regs: regs.as_mut_ptr(),
count: regs.len(),
@@ -2199,7 +2334,7 @@ impl Function {
where
I: IntoIterator<Item = CoreRegister>,
{
- let mut regs: Box<[u32]> = values.into_iter().map(|reg| reg.id()).collect();
+ let mut regs: Box<[u32]> = values.into_iter().map(|reg| reg.id().0).collect();
let mut regs = BNRegisterSetWithConfidence {
regs: regs.as_mut_ptr(),
count: regs.len(),
@@ -2217,33 +2352,42 @@ impl Function {
pub fn create_graph(
&self,
view_type: FunctionViewType,
- settings: Option<DisassemblySettings>,
+ settings: Option<&DisassemblySettings>,
) -> Ref<FlowGraph> {
- let settings_raw = settings.map(|s| s.handle).unwrap_or(core::ptr::null_mut());
- let result = unsafe { BNCreateFunctionGraph(self.handle, view_type.as_raw().0, settings_raw) };
+ let settings_raw = settings.map(|s| s.handle).unwrap_or(std::ptr::null_mut());
+ let raw_view_type = FunctionViewType::into_raw(view_type);
+ let result = unsafe { BNCreateFunctionGraph(self.handle, raw_view_type, settings_raw) };
+ FunctionViewType::free_raw(raw_view_type);
unsafe { Ref::new(FlowGraph::from_raw(result)) }
}
pub fn parent_components(&self) -> Array<Component> {
let mut count = 0;
- let result = unsafe{ BNGetFunctionParentComponents(self.view().handle, self.handle, &mut count) };
+ let result =
+ unsafe { BNGetFunctionParentComponents(self.view().handle, self.handle, &mut count) };
assert!(!result.is_null());
- unsafe{ Array::new(result, count, ()) }
+ unsafe { Array::new(result, count, ()) }
}
}
-impl fmt::Debug for Function {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(
- f,
- "<func '{}' ({}) {:x}>",
- self.symbol().full_name(),
- self.platform().name(),
- self.start()
- )
+impl Debug for Function {
+ fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
+ // TODO: I am sure there is more we should add to this.
+ f.debug_struct("Function")
+ .field("start", &self.start())
+ .field("arch", &self.arch())
+ .field("platform", &self.platform())
+ .field("symbol", &self.symbol())
+ .field("is_auto", &self.is_auto())
+ .field("tags", &self.tags().to_vec())
+ .field("comments", &self.comments().to_vec())
+ .finish()
}
}
+unsafe impl Send for Function {}
+unsafe impl Sync for Function {}
+
impl ToOwned for Function {
type Owned = Ref<Self>;
@@ -2271,11 +2415,12 @@ impl CoreArrayProvider for Function {
}
unsafe impl CoreArrayProviderInner for Function {
- unsafe fn free(raw: *mut *mut BNFunction, count: usize, _context: &()) {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
BNFreeFunctionList(raw, count);
}
- unsafe fn wrap_raw<'a>(raw: &'a *mut BNFunction, context: &'a ()) -> Self::Wrapped<'a> {
- Guard::new(Function { handle: *raw }, context)
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Guard::new(Self::from_raw(*raw), context)
}
}
@@ -2299,97 +2444,315 @@ impl PartialEq for Function {
}
}
-/////////////////
-// AddressRange
-
-#[repr(transparent)]
-pub struct AddressRange(pub(crate) BNAddressRange);
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct AddressRange {
+ pub start: u64,
+ pub end: u64,
+}
-impl AddressRange {
- pub fn start(&self) -> u64 {
- self.0.start
+impl From<BNAddressRange> for AddressRange {
+ fn from(raw: BNAddressRange) -> Self {
+ Self {
+ start: raw.start,
+ end: raw.end,
+ }
}
+}
- pub fn end(&self) -> u64 {
- self.0.end
+impl From<AddressRange> for BNAddressRange {
+ fn from(raw: AddressRange) -> Self {
+ Self {
+ start: raw.start,
+ end: raw.end,
+ }
}
}
impl CoreArrayProvider for AddressRange {
type Raw = BNAddressRange;
type Context = ();
- type Wrapped<'a> = &'a AddressRange;
+ type Wrapped<'a> = Self;
}
+
unsafe impl CoreArrayProviderInner for AddressRange {
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
BNFreeAddressRanges(raw);
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- mem::transmute(raw)
+ Self::from(*raw)
}
}
-/////////////////
-// PerformanceInfo
-
-// NOTE only exists as Array<PerformanceInfo>, cant be owned
-#[repr(transparent)]
-pub struct PerformanceInfo(BNPerformanceInfo);
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct PerformanceInfo {
+ pub name: String,
+ pub seconds: Duration,
+}
-impl PerformanceInfo {
- pub fn name(&self) -> &str {
- unsafe { std::ffi::CStr::from_ptr(self.0.name) }
- .to_str()
- .unwrap()
+impl From<BNPerformanceInfo> for PerformanceInfo {
+ fn from(value: BNPerformanceInfo) -> Self {
+ Self {
+ name: unsafe { BnString::from_raw(value.name) }.to_string(),
+ seconds: Duration::from_secs_f64(value.seconds),
+ }
}
- pub fn seconds(&self) -> f64 {
- self.0.seconds
+}
+
+impl From<&BNPerformanceInfo> for PerformanceInfo {
+ fn from(value: &BNPerformanceInfo) -> Self {
+ Self {
+ // TODO: Name will be freed by this. FIX!
+ name: unsafe { BnString::from_raw(value.name) }.to_string(),
+ seconds: Duration::from_secs_f64(value.seconds),
+ }
}
}
impl CoreArrayProvider for PerformanceInfo {
type Raw = BNPerformanceInfo;
type Context = ();
- type Wrapped<'a> = Guard<'a, PerformanceInfo>;
+ type Wrapped<'a> = Self;
}
+
unsafe impl CoreArrayProviderInner for PerformanceInfo {
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
BNFreeAnalysisPerformanceInfo(raw, count);
}
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
- Guard::new(Self(*raw), context)
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ // TODO: Swap this to the ref version.
+ Self::from(*raw)
}
}
-/////////////////
-// Comments
+// NOTE: only exists as part of an Array, never owned
+pub struct UnresolvedIndirectBranches(u64);
-// NOTE only exists as Array<Comments>, cant be owned
-pub struct Comments {
- addr: u64,
- comment: BnString,
+impl UnresolvedIndirectBranches {
+ pub fn address(&self) -> u64 {
+ self.0
+ }
}
-impl Comments {
- pub fn address(&self) -> u64 {
- self.addr
+impl CoreArrayProvider for UnresolvedIndirectBranches {
+ type Raw = u64;
+ type Context = ();
+ type Wrapped<'a> = Self;
+}
+
+unsafe impl CoreArrayProviderInner for UnresolvedIndirectBranches {
+ unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
+ BNFreeAddressList(raw)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self(*raw)
+ }
+}
+
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
+pub struct ConstantReference {
+ pub value: i64,
+ pub size: usize,
+ pub pointer: bool,
+ pub intermediate: bool,
+}
+
+impl From<BNConstantReference> for ConstantReference {
+ fn from(value: BNConstantReference) -> Self {
+ Self {
+ value: value.value,
+ size: value.size,
+ pointer: value.pointer,
+ intermediate: value.intermediate,
+ }
}
- pub fn comment(&self) -> &str {
- self.comment.as_str()
+}
+
+impl From<ConstantReference> for BNConstantReference {
+ fn from(value: ConstantReference) -> Self {
+ Self {
+ value: value.value,
+ size: value.size,
+ pointer: value.pointer,
+ intermediate: value.intermediate,
+ }
+ }
+}
+
+impl CoreArrayProvider for ConstantReference {
+ type Raw = BNConstantReference;
+ type Context = ();
+ type Wrapped<'a> = Self;
+}
+
+unsafe impl CoreArrayProviderInner for ConstantReference {
+ unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
+ BNFreeConstantReferenceList(raw)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::from(*raw)
+ }
+}
+
+#[derive(Debug, Copy, Clone)]
+pub struct RegisterStackAdjustment {
+ pub register_id: u32,
+ pub adjustment: Conf<i32>,
+}
+
+impl RegisterStackAdjustment {
+ pub fn new(register_id: u32, adjustment: impl Into<Conf<i32>>) -> Self {
+ Self {
+ register_id,
+ adjustment: adjustment.into(),
+ }
+ }
+}
+
+impl From<BNRegisterStackAdjustment> for RegisterStackAdjustment {
+ fn from(value: BNRegisterStackAdjustment) -> Self {
+ Self {
+ register_id: value.regStack,
+ adjustment: Conf::new(value.adjustment, value.confidence),
+ }
+ }
+}
+
+impl From<RegisterStackAdjustment> for BNRegisterStackAdjustment {
+ fn from(value: RegisterStackAdjustment) -> Self {
+ Self {
+ regStack: value.register_id,
+ adjustment: value.adjustment.contents,
+ confidence: value.adjustment.confidence,
+ }
+ }
+}
+
+impl CoreArrayProvider for RegisterStackAdjustment {
+ type Raw = BNRegisterStackAdjustment;
+ type Context = ();
+ type Wrapped<'a> = Self;
+}
+
+unsafe impl CoreArrayProviderInner for RegisterStackAdjustment {
+ unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
+ BNFreeRegisterStackAdjustments(raw)
}
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::from(*raw)
+ }
+}
+
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
+pub enum HighlightColor {
+ StandardHighlightColor {
+ color: HighlightStandardColor,
+ alpha: u8,
+ },
+ MixedHighlightColor {
+ color: HighlightStandardColor,
+ mix_color: HighlightStandardColor,
+ mix: u8,
+ alpha: u8,
+ },
+ CustomHighlightColor {
+ r: u8,
+ g: u8,
+ b: u8,
+ alpha: u8,
+ },
}
-impl CoreArrayProvider for Comments {
+impl From<BNHighlightColor> for HighlightColor {
+ fn from(value: BNHighlightColor) -> Self {
+ match value.style {
+ BNHighlightColorStyle::StandardHighlightColor => Self::StandardHighlightColor {
+ color: value.color,
+ alpha: value.alpha,
+ },
+ BNHighlightColorStyle::MixedHighlightColor => Self::MixedHighlightColor {
+ color: value.color,
+ mix_color: value.mixColor,
+ mix: value.mix,
+ alpha: value.alpha,
+ },
+ BNHighlightColorStyle::CustomHighlightColor => Self::CustomHighlightColor {
+ r: value.r,
+ g: value.g,
+ b: value.b,
+ alpha: value.alpha,
+ },
+ }
+ }
+}
+
+impl From<HighlightColor> for BNHighlightColor {
+ fn from(value: HighlightColor) -> Self {
+ match value {
+ HighlightColor::StandardHighlightColor { color, alpha } => BNHighlightColor {
+ style: BNHighlightColorStyle::StandardHighlightColor,
+ color,
+ alpha,
+ ..Default::default()
+ },
+ HighlightColor::MixedHighlightColor {
+ color,
+ mix_color,
+ mix,
+ alpha,
+ } => BNHighlightColor {
+ style: BNHighlightColorStyle::MixedHighlightColor,
+ color,
+ mixColor: mix_color,
+ mix,
+ alpha,
+ ..Default::default()
+ },
+ HighlightColor::CustomHighlightColor { r, g, b, alpha } => BNHighlightColor {
+ style: BNHighlightColorStyle::CustomHighlightColor,
+ r,
+ g,
+ b,
+ alpha,
+ ..Default::default()
+ },
+ }
+ }
+}
+
+impl Default for HighlightColor {
+ fn default() -> Self {
+ Self::StandardHighlightColor {
+ color: HighlightStandardColor::NoHighlightColor,
+ alpha: 0,
+ }
+ }
+}
+
+// NOTE only exists as Array<Comments>, cant be owned
+#[derive(Clone, Debug, Hash, Eq, PartialEq)]
+pub struct Comment {
+ pub addr: u64,
+ pub comment: BnString,
+}
+
+impl CoreArrayProvider for Comment {
type Raw = u64;
type Context = Ref<Function>;
- type Wrapped<'a> = Comments;
+ type Wrapped<'a> = Comment;
}
-unsafe impl CoreArrayProviderInner for Comments {
+
+unsafe impl CoreArrayProviderInner for Comment {
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
BNFreeAddressList(raw);
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, function: &'a Self::Context) -> Self::Wrapped<'a> {
- Comments {
+ Comment {
addr: *raw,
comment: function.comment_at(*raw),
}