From 501fe3ec7a63a534fca3926a5fc4267f6886f089 Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Sun, 7 Dec 2025 15:03:44 -0500 Subject: [Rust] Move architecture module code into more reasonable files To keep backwards compatibility for commonly referenced code we re-export them within the architecture module. Also does some light refactoring of some newly added APIs to keep them more consistent with other parts of the codebase. --- rust/src/architecture/branches.rs | 153 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 rust/src/architecture/branches.rs (limited to 'rust/src/architecture/branches.rs') diff --git a/rust/src/architecture/branches.rs b/rust/src/architecture/branches.rs new file mode 100644 index 00000000..ff0ab516 --- /dev/null +++ b/rust/src/architecture/branches.rs @@ -0,0 +1,153 @@ +use crate::architecture::CoreArchitecture; +use crate::function::Location; +use crate::rc::{CoreArrayProvider, CoreArrayProviderInner}; +use binaryninjacore_sys::*; + +pub use binaryninjacore_sys::BNBranchType as BranchType; + +#[derive(Default, Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub enum BranchKind { + #[default] + Unresolved, + Unconditional(u64), + False(u64), + True(u64), + Call(u64), + FunctionReturn, + SystemCall, + Indirect, + Exception, + UserDefined, +} + +#[derive(Default, Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct BranchInfo { + /// If `None` the target architecture is the same as the branch instruction. + pub arch: Option, + pub kind: BranchKind, +} + +impl BranchInfo { + /// Branches to an instruction with the current architecture. + pub fn new(kind: BranchKind) -> Self { + Self { arch: None, kind } + } + + /// Branches to an instruction with an explicit architecture. + /// + /// Use this if your architecture can transition to another architecture with a branch. + pub fn new_with_arch(kind: BranchKind, arch: CoreArchitecture) -> Self { + Self { + arch: Some(arch), + kind, + } + } + + pub fn target(&self) -> Option { + match self.kind { + BranchKind::Unconditional(target) => Some(target), + BranchKind::False(target) => Some(target), + BranchKind::True(target) => Some(target), + BranchKind::Call(target) => Some(target), + _ => None, + } + } +} + +impl From for BNBranchType { + fn from(value: BranchInfo) -> Self { + match value.kind { + BranchKind::Unresolved => BNBranchType::UnresolvedBranch, + BranchKind::Unconditional(_) => BNBranchType::UnconditionalBranch, + BranchKind::False(_) => BNBranchType::FalseBranch, + BranchKind::True(_) => BNBranchType::TrueBranch, + BranchKind::Call(_) => BNBranchType::CallDestination, + BranchKind::FunctionReturn => BNBranchType::FunctionReturn, + BranchKind::SystemCall => BNBranchType::SystemCall, + BranchKind::Indirect => BNBranchType::IndirectBranch, + BranchKind::Exception => BNBranchType::ExceptionBranch, + BranchKind::UserDefined => BNBranchType::UserDefinedBranch, + } + } +} + +impl From for BranchInfo { + fn from(value: BranchKind) -> Self { + Self { + arch: None, + kind: value, + } + } +} + +impl From for BranchType { + fn from(value: BranchKind) -> Self { + match value { + BranchKind::Unresolved => BranchType::UnresolvedBranch, + BranchKind::Unconditional(_) => BranchType::UnconditionalBranch, + BranchKind::True(_) => BranchType::TrueBranch, + BranchKind::False(_) => BranchType::FalseBranch, + BranchKind::Call(_) => BranchType::CallDestination, + BranchKind::FunctionReturn => BranchType::FunctionReturn, + BranchKind::SystemCall => BranchType::SystemCall, + BranchKind::Indirect => BranchType::IndirectBranch, + BranchKind::Exception => BranchType::ExceptionBranch, + BranchKind::UserDefined => BranchType::UserDefinedBranch, + } + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct IndirectBranchInfo { + pub source: Location, + pub dest: Location, + pub auto_defined: bool, +} + +impl From for IndirectBranchInfo { + fn from(value: BNIndirectBranchInfo) -> Self { + Self { + source: Location::from_raw(value.sourceAddr, value.sourceArch), + dest: Location::from_raw(value.destAddr, value.destArch), + auto_defined: value.autoDefined, + } + } +} + +impl From for BNIndirectBranchInfo { + fn from(value: IndirectBranchInfo) -> Self { + let source_arch = value + .source + .arch + .map(|a| a.handle) + .unwrap_or(std::ptr::null_mut()); + let dest_arch = value + .source + .arch + .map(|a| a.handle) + .unwrap_or(std::ptr::null_mut()); + Self { + sourceArch: source_arch, + sourceAddr: value.source.addr, + destArch: dest_arch, + destAddr: value.dest.addr, + autoDefined: value.auto_defined, + } + } +} + +impl CoreArrayProvider for IndirectBranchInfo { + type Raw = BNIndirectBranchInfo; + type Context = (); + type Wrapped<'a> = Self; +} + +unsafe impl CoreArrayProviderInner for IndirectBranchInfo { + unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) { + BNFreeIndirectBranchList(raw) + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::from(*raw) + } +} -- cgit v1.3.1