binaryninja/architecture/
register.rs1use crate::architecture::CoreArchitecture;
2use crate::rc::{CoreArrayProvider, CoreArrayProviderInner};
3use binaryninjacore_sys::*;
4use std::borrow::Cow;
5use std::ffi::CStr;
6use std::fmt::{Debug, Formatter};
7use std::hash::Hash;
8
9new_id_type!(RegisterId, u32);
10
11impl RegisterId {
12 pub fn is_temporary(&self) -> bool {
13 self.0 & 0x8000_0000 != 0
14 }
15}
16
17new_id_type!(RegisterStackId, u32);
18
19#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
20pub enum ImplicitRegisterExtend {
21 NoExtend = 0,
28 ZeroExtendToFullWidth,
35 SignExtendToFullWidth,
37}
38
39impl From<BNImplicitRegisterExtend> for ImplicitRegisterExtend {
40 fn from(value: BNImplicitRegisterExtend) -> Self {
41 match value {
42 BNImplicitRegisterExtend::NoExtend => Self::NoExtend,
43 BNImplicitRegisterExtend::ZeroExtendToFullWidth => Self::ZeroExtendToFullWidth,
44 BNImplicitRegisterExtend::SignExtendToFullWidth => Self::SignExtendToFullWidth,
45 }
46 }
47}
48
49impl From<ImplicitRegisterExtend> for BNImplicitRegisterExtend {
50 fn from(value: ImplicitRegisterExtend) -> Self {
51 match value {
52 ImplicitRegisterExtend::NoExtend => Self::NoExtend,
53 ImplicitRegisterExtend::ZeroExtendToFullWidth => Self::ZeroExtendToFullWidth,
54 ImplicitRegisterExtend::SignExtendToFullWidth => Self::SignExtendToFullWidth,
55 }
56 }
57}
58
59pub trait RegisterInfo: Sized {
61 type RegType: Register<InfoType = Self>;
62
63 fn parent(&self) -> Option<Self::RegType>;
69
70 fn size(&self) -> usize;
72
73 fn offset(&self) -> usize;
75
76 fn implicit_extend(&self) -> ImplicitRegisterExtend;
78}
79
80pub trait Register: Debug + Sized + Clone + Copy + Hash + Eq {
81 type InfoType: RegisterInfo<RegType = Self>;
82
83 fn name(&self) -> Cow<'_, str>;
85
86 fn info(&self) -> Self::InfoType;
87
88 fn id(&self) -> RegisterId;
92}
93
94pub trait RegisterStackInfo: Sized {
96 type RegStackType: RegisterStack<InfoType = Self>;
97 type RegType: Register<InfoType = Self::RegInfoType>;
98 type RegInfoType: RegisterInfo<RegType = Self::RegType>;
99
100 fn storage_regs(&self) -> (Self::RegType, usize);
112
113 fn top_relative_regs(&self) -> Option<(Self::RegType, usize)>;
123
124 fn stack_top_reg(&self) -> Self::RegType;
136}
137
138pub trait RegisterStack: Debug + Sized + Clone + Copy {
147 type InfoType: RegisterStackInfo<
148 RegType = Self::RegType,
149 RegInfoType = Self::RegInfoType,
150 RegStackType = Self,
151 >;
152 type RegType: Register<InfoType = Self::RegInfoType>;
153 type RegInfoType: RegisterInfo<RegType = Self::RegType>;
154
155 fn name(&self) -> Cow<'_, str>;
156 fn info(&self) -> Self::InfoType;
157
158 fn id(&self) -> RegisterStackId;
162}
163
164#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
166pub struct UnusedRegisterStack<R: Register> {
167 _reg: std::marker::PhantomData<R>,
168}
169
170impl<R: Register> RegisterStack for UnusedRegisterStack<R> {
171 type InfoType = Self;
172 type RegType = R;
173 type RegInfoType = R::InfoType;
174
175 fn name(&self) -> Cow<'_, str> {
176 unreachable!()
177 }
178 fn info(&self) -> Self::InfoType {
179 unreachable!()
180 }
181 fn id(&self) -> RegisterStackId {
182 unreachable!()
183 }
184}
185
186impl<R: Register> RegisterStackInfo for UnusedRegisterStack<R> {
187 type RegStackType = Self;
188 type RegType = R;
189 type RegInfoType = R::InfoType;
190
191 fn storage_regs(&self) -> (Self::RegType, usize) {
192 unreachable!()
193 }
194 fn top_relative_regs(&self) -> Option<(Self::RegType, usize)> {
195 unreachable!()
196 }
197 fn stack_top_reg(&self) -> Self::RegType {
198 unreachable!()
199 }
200}
201
202#[derive(Debug, Copy, Clone)]
203pub struct CoreRegisterInfo {
204 arch: CoreArchitecture,
205 id: RegisterId,
206 info: BNRegisterInfo,
207}
208
209impl CoreRegisterInfo {
210 pub fn new(arch: CoreArchitecture, id: RegisterId, info: BNRegisterInfo) -> Self {
211 Self { arch, id, info }
212 }
213}
214
215impl RegisterInfo for CoreRegisterInfo {
216 type RegType = CoreRegister;
217
218 fn parent(&self) -> Option<CoreRegister> {
219 if self.id != RegisterId::from(self.info.fullWidthRegister) {
220 Some(CoreRegister::new(
221 self.arch,
222 RegisterId::from(self.info.fullWidthRegister),
223 )?)
224 } else {
225 None
226 }
227 }
228
229 fn size(&self) -> usize {
230 self.info.size
231 }
232
233 fn offset(&self) -> usize {
234 self.info.offset
235 }
236
237 fn implicit_extend(&self) -> ImplicitRegisterExtend {
238 self.info.extend.into()
239 }
240}
241
242#[derive(Copy, Clone, Eq, PartialEq, Hash)]
243pub struct CoreRegister {
244 arch: CoreArchitecture,
245 id: RegisterId,
246}
247
248impl CoreRegister {
249 pub fn new(arch: CoreArchitecture, id: RegisterId) -> Option<Self> {
250 let register = Self { arch, id };
251 register.is_valid().then_some(register)
252 }
253
254 fn is_valid(&self) -> bool {
255 let name = unsafe { BNGetArchitectureRegisterName(self.arch.handle, self.id.into()) };
257 match name.is_null() {
258 true => false,
259 false => {
260 unsafe { BNFreeString(name) };
261 true
262 }
263 }
264 }
265}
266
267impl Register for CoreRegister {
268 type InfoType = CoreRegisterInfo;
269
270 fn name(&self) -> Cow<'_, str> {
271 unsafe {
272 let name = BNGetArchitectureRegisterName(self.arch.handle, self.id.into());
273
274 let res = CStr::from_ptr(name);
278 let res = res.to_string_lossy().into_owned().into();
279
280 BNFreeString(name);
281
282 res
283 }
284 }
285
286 fn info(&self) -> CoreRegisterInfo {
287 CoreRegisterInfo::new(self.arch, self.id, unsafe {
288 BNGetArchitectureRegisterInfo(self.arch.handle, self.id.into())
289 })
290 }
291
292 fn id(&self) -> RegisterId {
293 self.id
294 }
295}
296
297impl Debug for CoreRegister {
298 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
299 f.debug_struct("CoreRegister")
300 .field("id", &self.id)
301 .field("name", &self.name())
302 .finish()
303 }
304}
305
306impl CoreArrayProvider for CoreRegister {
307 type Raw = u32;
308 type Context = CoreArchitecture;
309 type Wrapped<'a> = Self;
310}
311
312unsafe impl CoreArrayProviderInner for CoreRegister {
313 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
314 BNFreeRegisterList(raw)
315 }
316
317 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
318 Self::new(*context, RegisterId::from(*raw)).expect("Register list contains valid registers")
319 }
320}
321
322#[derive(Debug, Copy, Clone)]
323pub struct CoreRegisterStackInfo {
324 arch: CoreArchitecture,
325 info: BNRegisterStackInfo,
327}
328
329impl CoreRegisterStackInfo {
330 pub fn new(arch: CoreArchitecture, info: BNRegisterStackInfo) -> Self {
331 Self { arch, info }
332 }
333}
334
335impl RegisterStackInfo for CoreRegisterStackInfo {
336 type RegStackType = CoreRegisterStack;
337 type RegType = CoreRegister;
338 type RegInfoType = CoreRegisterInfo;
339
340 fn storage_regs(&self) -> (Self::RegType, usize) {
341 (
342 CoreRegister::new(self.arch, RegisterId::from(self.info.firstStorageReg))
343 .expect("Storage register is valid"),
344 self.info.storageCount as usize,
345 )
346 }
347
348 fn top_relative_regs(&self) -> Option<(Self::RegType, usize)> {
349 if self.info.topRelativeCount == 0 {
350 None
351 } else {
352 Some((
353 CoreRegister::new(self.arch, RegisterId::from(self.info.firstTopRelativeReg))
354 .expect("Top relative register is valid"),
355 self.info.topRelativeCount as usize,
356 ))
357 }
358 }
359
360 fn stack_top_reg(&self) -> Self::RegType {
361 CoreRegister::new(self.arch, RegisterId::from(self.info.stackTopReg))
362 .expect("Stack top register is valid")
363 }
364}
365
366#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
367pub struct CoreRegisterStack {
368 arch: CoreArchitecture,
369 id: RegisterStackId,
370}
371
372impl CoreRegisterStack {
373 pub fn new(arch: CoreArchitecture, id: RegisterStackId) -> Option<Self> {
374 let register_stack = Self { arch, id };
375 register_stack.is_valid().then_some(register_stack)
376 }
377
378 fn is_valid(&self) -> bool {
379 let name = unsafe { BNGetArchitectureRegisterStackName(self.arch.handle, self.id.into()) };
381 match name.is_null() {
382 true => false,
383 false => {
384 unsafe { BNFreeString(name) };
385 true
386 }
387 }
388 }
389}
390
391impl RegisterStack for CoreRegisterStack {
392 type InfoType = CoreRegisterStackInfo;
393 type RegType = CoreRegister;
394 type RegInfoType = CoreRegisterInfo;
395
396 fn name(&self) -> Cow<'_, str> {
397 unsafe {
398 let name = BNGetArchitectureRegisterStackName(self.arch.handle, self.id.into());
399
400 let res = CStr::from_ptr(name);
404 let res = res.to_string_lossy().into_owned().into();
405
406 BNFreeString(name);
407
408 res
409 }
410 }
411
412 fn info(&self) -> CoreRegisterStackInfo {
413 CoreRegisterStackInfo::new(self.arch, unsafe {
414 BNGetArchitectureRegisterStackInfo(self.arch.handle, self.id.into())
415 })
416 }
417
418 fn id(&self) -> RegisterStackId {
419 self.id
420 }
421}