binaryninja/architecture/
branches.rs

1use crate::architecture::CoreArchitecture;
2use crate::function::Location;
3use crate::rc::{CoreArrayProvider, CoreArrayProviderInner};
4use binaryninjacore_sys::*;
5
6pub use binaryninjacore_sys::BNBranchType as BranchType;
7
8#[derive(Default, Copy, Clone, PartialEq, Eq, Hash, Debug)]
9pub enum BranchKind {
10    #[default]
11    Unresolved,
12    Unconditional(u64),
13    False(u64),
14    True(u64),
15    Call(u64),
16    FunctionReturn,
17    SystemCall,
18    Indirect,
19    Exception,
20    UserDefined,
21}
22
23#[derive(Default, Copy, Clone, PartialEq, Eq, Hash, Debug)]
24pub struct BranchInfo {
25    /// If `None`, the target architecture is the same as the branching instruction.
26    pub arch: Option<CoreArchitecture>,
27    pub kind: BranchKind,
28}
29
30impl BranchInfo {
31    /// Branches to an instruction with the current architecture.
32    pub fn new(kind: BranchKind) -> Self {
33        Self { arch: None, kind }
34    }
35
36    /// Branches to an instruction with an explicit architecture.
37    ///
38    /// Use this if your architecture can transition to another architecture with a branch.
39    pub fn new_with_arch(kind: BranchKind, arch: CoreArchitecture) -> Self {
40        Self {
41            arch: Some(arch),
42            kind,
43        }
44    }
45
46    pub fn target(&self) -> Option<u64> {
47        match self.kind {
48            BranchKind::Unconditional(target) => Some(target),
49            BranchKind::False(target) => Some(target),
50            BranchKind::True(target) => Some(target),
51            BranchKind::Call(target) => Some(target),
52            _ => None,
53        }
54    }
55}
56
57impl From<BranchInfo> for BNBranchType {
58    fn from(value: BranchInfo) -> Self {
59        match value.kind {
60            BranchKind::Unresolved => BNBranchType::UnresolvedBranch,
61            BranchKind::Unconditional(_) => BNBranchType::UnconditionalBranch,
62            BranchKind::False(_) => BNBranchType::FalseBranch,
63            BranchKind::True(_) => BNBranchType::TrueBranch,
64            BranchKind::Call(_) => BNBranchType::CallDestination,
65            BranchKind::FunctionReturn => BNBranchType::FunctionReturn,
66            BranchKind::SystemCall => BNBranchType::SystemCall,
67            BranchKind::Indirect => BNBranchType::IndirectBranch,
68            BranchKind::Exception => BNBranchType::ExceptionBranch,
69            BranchKind::UserDefined => BNBranchType::UserDefinedBranch,
70        }
71    }
72}
73
74impl From<BranchKind> for BranchInfo {
75    fn from(value: BranchKind) -> Self {
76        Self {
77            arch: None,
78            kind: value,
79        }
80    }
81}
82
83impl From<BranchKind> for BranchType {
84    fn from(value: BranchKind) -> Self {
85        match value {
86            BranchKind::Unresolved => BranchType::UnresolvedBranch,
87            BranchKind::Unconditional(_) => BranchType::UnconditionalBranch,
88            BranchKind::True(_) => BranchType::TrueBranch,
89            BranchKind::False(_) => BranchType::FalseBranch,
90            BranchKind::Call(_) => BranchType::CallDestination,
91            BranchKind::FunctionReturn => BranchType::FunctionReturn,
92            BranchKind::SystemCall => BranchType::SystemCall,
93            BranchKind::Indirect => BranchType::IndirectBranch,
94            BranchKind::Exception => BranchType::ExceptionBranch,
95            BranchKind::UserDefined => BranchType::UserDefinedBranch,
96        }
97    }
98}
99
100#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
101pub struct IndirectBranchInfo {
102    pub source: Location,
103    pub dest: Location,
104    pub auto_defined: bool,
105}
106
107impl From<BNIndirectBranchInfo> for IndirectBranchInfo {
108    fn from(value: BNIndirectBranchInfo) -> Self {
109        Self {
110            source: Location::from_raw(value.sourceAddr, value.sourceArch),
111            dest: Location::from_raw(value.destAddr, value.destArch),
112            auto_defined: value.autoDefined,
113        }
114    }
115}
116
117impl From<IndirectBranchInfo> for BNIndirectBranchInfo {
118    fn from(value: IndirectBranchInfo) -> Self {
119        let source_arch = value
120            .source
121            .arch
122            .map(|a| a.handle)
123            .unwrap_or(std::ptr::null_mut());
124        let dest_arch = value
125            .source
126            .arch
127            .map(|a| a.handle)
128            .unwrap_or(std::ptr::null_mut());
129        Self {
130            sourceArch: source_arch,
131            sourceAddr: value.source.addr,
132            destArch: dest_arch,
133            destAddr: value.dest.addr,
134            autoDefined: value.auto_defined,
135        }
136    }
137}
138
139impl From<&BNIndirectBranchInfo> for IndirectBranchInfo {
140    fn from(value: &BNIndirectBranchInfo) -> Self {
141        Self::from(*value)
142    }
143}
144
145impl CoreArrayProvider for IndirectBranchInfo {
146    type Raw = BNIndirectBranchInfo;
147    type Context = ();
148    type Wrapped<'a> = Self;
149}
150
151unsafe impl CoreArrayProviderInner for IndirectBranchInfo {
152    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
153        BNFreeIndirectBranchList(raw)
154    }
155
156    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
157        Self::from(*raw)
158    }
159}