binaryninja/architecture/
intrinsic.rs1use crate::architecture::CoreArchitecture;
2use crate::confidence::Conf;
3use crate::rc::Ref;
4use crate::types::{NameAndType, Type};
5use binaryninjacore_sys::{
6 BNFreeNameAndTypeList, BNFreeOutputTypeList, BNFreeString, BNGetArchitectureIntrinsicClass,
7 BNGetArchitectureIntrinsicInputs, BNGetArchitectureIntrinsicName,
8 BNGetArchitectureIntrinsicOutputs, BNIntrinsicClass,
9};
10use std::borrow::Cow;
11use std::ffi::CStr;
12use std::fmt::{Debug, Formatter};
13
14new_id_type!(IntrinsicId, u32);
15
16pub trait Intrinsic: Debug + Sized + Clone + Copy {
17 fn name(&self) -> Cow<'_, str>;
18
19 fn id(&self) -> IntrinsicId;
21
22 fn class(&self) -> BNIntrinsicClass {
24 BNIntrinsicClass::GeneralIntrinsicClass
25 }
26
27 fn inputs(&self) -> Vec<NameAndType>;
30
31 fn outputs(&self) -> Vec<Conf<Ref<Type>>>;
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
37pub struct UnusedIntrinsic;
38
39impl Intrinsic for UnusedIntrinsic {
40 fn name(&self) -> Cow<'_, str> {
41 unreachable!()
42 }
43 fn id(&self) -> IntrinsicId {
44 unreachable!()
45 }
46 fn inputs(&self) -> Vec<NameAndType> {
47 unreachable!()
48 }
49 fn outputs(&self) -> Vec<Conf<Ref<Type>>> {
50 unreachable!()
51 }
52}
53
54#[derive(Copy, Clone, Eq, PartialEq)]
55pub struct CoreIntrinsic {
56 pub arch: CoreArchitecture,
57 pub id: IntrinsicId,
58}
59
60impl CoreIntrinsic {
61 pub fn new(arch: CoreArchitecture, id: IntrinsicId) -> Option<Self> {
62 let intrinsic = Self { arch, id };
63 intrinsic.is_valid().then_some(intrinsic)
64 }
65
66 fn is_valid(&self) -> bool {
67 let name = unsafe { BNGetArchitectureIntrinsicName(self.arch.handle, self.id.into()) };
69 match name.is_null() {
70 true => false,
71 false => {
72 unsafe { BNFreeString(name) };
73 true
74 }
75 }
76 }
77}
78
79impl Intrinsic for CoreIntrinsic {
80 fn name(&self) -> Cow<'_, str> {
81 unsafe {
82 let name = BNGetArchitectureIntrinsicName(self.arch.handle, self.id.into());
83
84 let res = CStr::from_ptr(name);
89 let res = res.to_string_lossy().into_owned().into();
90
91 BNFreeString(name);
92
93 res
94 }
95 }
96
97 fn id(&self) -> IntrinsicId {
98 self.id
99 }
100
101 fn class(&self) -> BNIntrinsicClass {
102 unsafe { BNGetArchitectureIntrinsicClass(self.arch.handle, self.id.into()) }
103 }
104
105 fn inputs(&self) -> Vec<NameAndType> {
106 let mut count: usize = 0;
107 unsafe {
108 let inputs =
109 BNGetArchitectureIntrinsicInputs(self.arch.handle, self.id.into(), &mut count);
110
111 let ret = std::slice::from_raw_parts_mut(inputs, count)
112 .iter()
113 .map(NameAndType::from_raw)
114 .collect();
115
116 BNFreeNameAndTypeList(inputs, count);
117
118 ret
119 }
120 }
121
122 fn outputs(&self) -> Vec<Conf<Ref<Type>>> {
123 let mut count: usize = 0;
124 unsafe {
125 let inputs =
126 BNGetArchitectureIntrinsicOutputs(self.arch.handle, self.id.into(), &mut count);
127
128 let ret = std::slice::from_raw_parts_mut(inputs, count)
129 .iter()
130 .map(Conf::<Ref<Type>>::from_raw)
131 .collect();
132
133 BNFreeOutputTypeList(inputs, count);
134
135 ret
136 }
137 }
138}
139
140impl Debug for CoreIntrinsic {
141 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
142 f.debug_struct("CoreIntrinsic")
143 .field("id", &self.id)
144 .field("name", &self.name())
145 .field("class", &self.class())
146 .field("inputs", &self.inputs())
147 .field("outputs", &self.outputs())
148 .finish()
149 }
150}