1use crate::confidence::Conf;
2use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable};
3use crate::string::{raw_to_string, BnString, IntoCStr};
4use crate::types::{
5 MemberAccess, MemberScope, NamedTypeReference, StructureType, Type, TypeContainer,
6};
7use binaryninjacore_sys::*;
8use std::fmt::{Debug, Formatter};
9
10#[allow(unused)]
12use crate::binary_view::BinaryView;
13
14#[derive(PartialEq, Eq, Hash)]
15pub struct StructureBuilder {
16 pub(crate) handle: *mut BNStructureBuilder,
17}
18
19impl StructureBuilder {
70 pub fn new() -> Self {
71 Self {
72 handle: unsafe { BNCreateStructureBuilder() },
73 }
74 }
75
76 pub(crate) unsafe fn from_raw(handle: *mut BNStructureBuilder) -> Self {
77 debug_assert!(!handle.is_null());
78 Self { handle }
79 }
80
81 pub fn finalize(&self) -> Ref<Structure> {
83 let raw_struct_ptr = unsafe { BNFinalizeStructureBuilder(self.handle) };
84 unsafe { Structure::ref_from_raw(raw_struct_ptr) }
85 }
86
87 pub fn width(&mut self, width: u64) -> &mut Self {
93 unsafe {
94 BNSetStructureBuilderWidth(self.handle, width);
95 }
96 self
97 }
98
99 pub fn alignment(&mut self, alignment: usize) -> &mut Self {
100 unsafe {
101 BNSetStructureBuilderAlignment(self.handle, alignment);
102 }
103 self
104 }
105
106 pub fn packed(&mut self, packed: bool) -> &mut Self {
110 unsafe {
111 BNSetStructureBuilderPacked(self.handle, packed);
112 }
113 self
114 }
115
116 pub fn structure_type(&mut self, t: StructureType) -> &mut Self {
117 unsafe { BNSetStructureBuilderType(self.handle, t) };
118 self
119 }
120
121 pub fn pointer_offset(&mut self, offset: i64) -> &mut Self {
122 unsafe { BNSetStructureBuilderPointerOffset(self.handle, offset) };
123 self
124 }
125
126 pub fn propagates_data_var_refs(&mut self, propagates: bool) -> &mut Self {
127 unsafe { BNSetStructureBuilderPropagatesDataVariableReferences(self.handle, propagates) };
128 self
129 }
130
131 pub fn base_structures(&mut self, bases: &[BaseStructure]) -> &mut Self {
132 let raw_base_structs: Vec<BNBaseStructure> =
133 bases.iter().map(BaseStructure::into_owned_raw).collect();
134 unsafe {
135 BNSetBaseStructuresForStructureBuilder(
136 self.handle,
137 raw_base_structs.as_ptr() as *mut _,
138 raw_base_structs.len(),
139 )
140 };
141 self
142 }
143
144 pub fn append<'a, T: Into<Conf<&'a Type>>>(
152 &mut self,
153 ty: T,
154 name: &str,
155 access: MemberAccess,
156 scope: MemberScope,
157 ) -> &mut Self {
158 let name = name.to_cstr();
159 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
160 unsafe {
161 BNAddStructureBuilderMember(
162 self.handle,
163 &owned_raw_ty,
164 name.as_ref().as_ptr() as _,
165 access,
166 scope,
167 );
168 }
169 self
170 }
171
172 pub fn insert_member(
180 &mut self,
181 member: StructureMember,
182 overwrite_existing: bool,
183 ) -> &mut Self {
184 self.insert_bitwise(
185 &member.ty,
186 &member.name,
187 member.bit_offset(),
188 member.bit_width,
189 overwrite_existing,
190 member.access,
191 member.scope,
192 );
193 self
194 }
195
196 pub fn insert<'a, T: Into<Conf<&'a Type>>>(
201 &mut self,
202 ty: T,
203 name: &str,
204 offset: u64,
205 overwrite_existing: bool,
206 access: MemberAccess,
207 scope: MemberScope,
208 ) -> &mut Self {
209 self.insert_bitwise(
210 ty,
211 name,
212 offset * 8,
213 None,
214 overwrite_existing,
215 access,
216 scope,
217 )
218 }
219
220 pub fn insert_bitwise<'a, T: Into<Conf<&'a Type>>>(
225 &mut self,
226 ty: T,
227 name: &str,
228 bit_offset: u64,
229 bit_width: Option<u8>,
230 overwrite_existing: bool,
231 access: MemberAccess,
232 scope: MemberScope,
233 ) -> &mut Self {
234 let name = name.to_cstr();
235 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
236 let byte_offset = bit_offset / 8;
237 let bit_position = bit_offset % 8;
238 unsafe {
239 BNAddStructureBuilderMemberAtOffset(
240 self.handle,
241 &owned_raw_ty,
242 name.as_ref().as_ptr() as _,
243 byte_offset,
244 overwrite_existing,
245 access,
246 scope,
247 bit_position as u8,
248 bit_width.unwrap_or(0),
249 );
250 }
251 self
252 }
253
254 pub fn replace<'a, T: Into<Conf<&'a Type>>>(
255 &mut self,
256 index: usize,
257 ty: T,
258 name: &str,
259 overwrite_existing: bool,
260 ) -> &mut Self {
261 let name = name.to_cstr();
262 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
263 unsafe {
264 BNReplaceStructureBuilderMember(
265 self.handle,
266 index,
267 &owned_raw_ty,
268 name.as_ref().as_ptr() as _,
269 overwrite_existing,
270 )
271 }
272 self
273 }
274
275 pub fn remove(&mut self, index: usize) -> &mut Self {
277 unsafe { BNRemoveStructureBuilderMember(self.handle, index) };
278 self
279 }
280
281 pub fn current_width(&self) -> u64 {
286 unsafe { BNGetStructureBuilderWidth(self.handle) }
287 }
288}
289
290impl From<&Structure> for StructureBuilder {
291 fn from(structure: &Structure) -> StructureBuilder {
292 unsafe { Self::from_raw(BNCreateStructureBuilderFromStructure(structure.handle)) }
293 }
294}
295
296impl From<Vec<StructureMember>> for StructureBuilder {
297 fn from(members: Vec<StructureMember>) -> StructureBuilder {
298 let mut builder = StructureBuilder::new();
299 for member in members {
300 builder.insert_member(member, false);
301 }
302 builder
303 }
304}
305
306impl Drop for StructureBuilder {
307 fn drop(&mut self) {
308 unsafe { BNFreeStructureBuilder(self.handle) };
309 }
310}
311
312impl Default for StructureBuilder {
313 fn default() -> Self {
314 Self::new()
315 }
316}
317
318#[derive(PartialEq, Eq, Hash)]
319pub struct Structure {
320 pub(crate) handle: *mut BNStructure,
321}
322
323impl Structure {
324 pub(crate) unsafe fn ref_from_raw(handle: *mut BNStructure) -> Ref<Self> {
325 debug_assert!(!handle.is_null());
326 Ref::new(Self { handle })
327 }
328
329 pub fn builder() -> StructureBuilder {
330 StructureBuilder::new()
331 }
332
333 pub fn width(&self) -> u64 {
334 unsafe { BNGetStructureWidth(self.handle) }
335 }
336
337 pub fn structure_type(&self) -> StructureType {
338 unsafe { BNGetStructureType(self.handle) }
339 }
340
341 pub fn members_at_offset(
353 &self,
354 container: &TypeContainer,
355 offset: u64,
356 ) -> Vec<StructureMember> {
357 self.members_including_inherited(container)
358 .into_iter()
359 .filter(|m| m.member.is_offset_valid(offset))
360 .map(|m| m.member)
361 .collect()
362 }
363
364 pub fn members(&self) -> Vec<StructureMember> {
369 unsafe {
370 let mut count = 0;
371 let members_raw_ptr: *mut BNStructureMember =
372 BNGetStructureMembers(self.handle, &mut count);
373 debug_assert!(!members_raw_ptr.is_null());
374 let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
375 let members = members_raw.iter().map(StructureMember::from_raw).collect();
376 BNFreeStructureMemberList(members_raw_ptr, count);
377 members
378 }
379 }
380
381 pub fn members_including_inherited(
386 &self,
387 container: &TypeContainer,
388 ) -> Vec<InheritedStructureMember> {
389 unsafe {
390 let mut count = 0;
391 let members_raw_ptr: *mut BNInheritedStructureMember =
392 BNGetStructureMembersIncludingInherited(
393 self.handle,
394 container.handle.as_ptr(),
395 &mut count,
396 );
397 debug_assert!(!members_raw_ptr.is_null());
398 let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
399 let members = members_raw
400 .iter()
401 .map(InheritedStructureMember::from_raw)
402 .collect();
403 BNFreeInheritedStructureMemberList(members_raw_ptr, count);
404 members
405 }
406 }
407
408 pub fn base_structures(&self) -> Vec<BaseStructure> {
411 let mut count = 0;
412 let bases_raw_ptr = unsafe { BNGetBaseStructuresForStructure(self.handle, &mut count) };
413 debug_assert!(!bases_raw_ptr.is_null());
414 let bases_raw = unsafe { std::slice::from_raw_parts(bases_raw_ptr, count) };
415 let bases = bases_raw.iter().map(BaseStructure::from_raw).collect();
416 unsafe { BNFreeBaseStructureList(bases_raw_ptr, count) };
417 bases
418 }
419
420 pub fn is_packed(&self) -> bool {
422 unsafe { BNIsStructurePacked(self.handle) }
423 }
424
425 pub fn alignment(&self) -> usize {
426 unsafe { BNGetStructureAlignment(self.handle) }
427 }
428}
429
430impl Debug for Structure {
431 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
432 f.debug_struct("Structure")
433 .field("width", &self.width())
434 .field("alignment", &self.alignment())
435 .field("packed", &self.is_packed())
436 .field("structure_type", &self.structure_type())
437 .field("base_structures", &self.base_structures())
438 .field("members", &self.members())
439 .finish()
440 }
441}
442
443unsafe impl RefCountable for Structure {
444 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
445 Self::ref_from_raw(BNNewStructureReference(handle.handle))
446 }
447
448 unsafe fn dec_ref(handle: &Self) {
449 BNFreeStructure(handle.handle);
450 }
451}
452
453impl ToOwned for Structure {
454 type Owned = Ref<Self>;
455
456 fn to_owned(&self) -> Self::Owned {
457 unsafe { RefCountable::inc_ref(self) }
458 }
459}
460
461#[derive(Debug, Clone, Hash, PartialEq, Eq)]
462pub struct StructureMember {
463 pub ty: Conf<Ref<Type>>,
464 pub name: String,
466 pub offset: u64,
468 pub access: MemberAccess,
469 pub scope: MemberScope,
470 pub bit_position: Option<u8>,
472 pub bit_width: Option<u8>,
473}
474
475impl StructureMember {
476 pub(crate) fn from_raw(value: &BNStructureMember) -> Self {
477 Self {
478 ty: Conf::new(
479 unsafe { Type::from_raw(value.type_) }.to_owned(),
480 value.typeConfidence,
481 ),
482 name: raw_to_string(value.name as *mut _).unwrap(),
484 offset: value.offset,
485 access: value.access,
486 scope: value.scope,
487 bit_position: match value.bitPosition {
488 0 => None,
489 _ => Some(value.bitPosition),
490 },
491 bit_width: match value.bitWidth {
492 0 => None,
493 _ => Some(value.bitWidth),
494 },
495 }
496 }
497
498 #[allow(unused)]
499 pub(crate) fn from_owned_raw(value: BNStructureMember) -> Self {
500 let owned = Self::from_raw(&value);
501 Self::free_raw(value);
502 owned
503 }
504
505 #[allow(unused)]
506 pub(crate) fn into_raw(value: Self) -> BNStructureMember {
507 let bn_name = BnString::new(value.name);
508 BNStructureMember {
509 type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
510 name: BnString::into_raw(bn_name),
511 offset: value.offset,
512 typeConfidence: value.ty.confidence,
513 access: value.access,
514 scope: value.scope,
515 bitPosition: value.bit_position.unwrap_or(0),
516 bitWidth: value.bit_width.unwrap_or(0),
517 }
518 }
519
520 #[allow(unused)]
521 pub(crate) fn free_raw(value: BNStructureMember) {
522 let _ = unsafe { Type::ref_from_raw(value.type_) };
523 unsafe { BnString::free_raw(value.name) };
524 }
525
526 pub fn new(
527 ty: Conf<Ref<Type>>,
528 name: String,
529 offset: u64,
530 access: MemberAccess,
531 scope: MemberScope,
532 ) -> Self {
533 Self {
534 ty,
535 name,
536 offset,
537 access,
538 scope,
539 bit_position: None,
540 bit_width: None,
541 }
542 }
543
544 pub fn new_bitfield(
545 ty: Conf<Ref<Type>>,
546 name: String,
547 bit_offset: u64,
548 bit_width: u8,
549 access: MemberAccess,
550 scope: MemberScope,
551 ) -> Self {
552 Self {
553 ty,
554 name,
555 offset: bit_offset / 8,
556 access,
557 scope,
558 bit_position: Some((bit_offset % 8) as u8),
559 bit_width: Some(bit_width),
560 }
561 }
562
563 pub fn is_offset_valid(&self, offset: u64) -> bool {
566 self.offset <= offset && offset < self.offset + self.ty.contents.width()
567 }
568
569 pub fn bit_offset(&self) -> u64 {
571 (self.offset * 8) + self.bit_position.unwrap_or(0) as u64
572 }
573
574 pub fn width_in_bits(&self) -> u64 {
579 self.bit_width
580 .map(|w| w as u64)
581 .unwrap_or(self.ty.contents.width() * 8)
582 }
583}
584
585impl CoreArrayProvider for StructureMember {
586 type Raw = BNStructureMember;
587 type Context = ();
588 type Wrapped<'a> = Self;
589}
590
591unsafe impl CoreArrayProviderInner for StructureMember {
592 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
593 BNFreeStructureMemberList(raw, count)
594 }
595
596 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
597 Self::from_raw(raw)
598 }
599}
600
601#[derive(Debug, Clone, Hash, PartialEq, Eq)]
602pub struct InheritedStructureMember {
603 pub base: Ref<NamedTypeReference>,
604 pub base_offset: u64,
605 pub member: StructureMember,
606 pub member_index: usize,
607}
608
609impl InheritedStructureMember {
610 pub(crate) fn from_raw(value: &BNInheritedStructureMember) -> Self {
611 Self {
612 base: unsafe { NamedTypeReference::from_raw(value.base) }.to_owned(),
613 base_offset: value.baseOffset,
614 member: StructureMember::from_raw(&value.member),
615 member_index: value.memberIndex,
616 }
617 }
618
619 #[allow(unused)]
620 pub(crate) fn from_owned_raw(value: BNInheritedStructureMember) -> Self {
621 let owned = Self::from_raw(&value);
622 Self::free_raw(value);
623 owned
624 }
625
626 #[allow(unused)]
627 pub(crate) fn into_raw(value: Self) -> BNInheritedStructureMember {
628 BNInheritedStructureMember {
629 base: unsafe { Ref::into_raw(value.base) }.handle,
630 baseOffset: value.base_offset,
631 member: StructureMember::into_raw(value.member),
632 memberIndex: value.member_index,
633 }
634 }
635
636 #[allow(unused)]
637 pub(crate) fn free_raw(value: BNInheritedStructureMember) {
638 let _ = unsafe { NamedTypeReference::ref_from_raw(value.base) };
639 StructureMember::free_raw(value.member);
640 }
641
642 pub fn new(
643 base: Ref<NamedTypeReference>,
644 base_offset: u64,
645 member: StructureMember,
646 member_index: usize,
647 ) -> Self {
648 Self {
649 base,
650 base_offset,
651 member,
652 member_index,
653 }
654 }
655}
656
657#[derive(Debug, Clone, Hash, PartialEq, Eq)]
658pub struct BaseStructure {
659 pub ty: Ref<NamedTypeReference>,
660 pub offset: u64,
661 pub width: u64,
662}
663
664impl BaseStructure {
665 pub(crate) fn from_raw(value: &BNBaseStructure) -> Self {
666 Self {
667 ty: unsafe { NamedTypeReference::from_raw(value.type_) }.to_owned(),
668 offset: value.offset,
669 width: value.width,
670 }
671 }
672
673 #[allow(unused)]
674 pub(crate) fn from_owned_raw(value: BNBaseStructure) -> Self {
675 let owned = Self::from_raw(&value);
676 Self::free_raw(value);
677 owned
678 }
679
680 #[allow(unused)]
681 pub(crate) fn into_raw(value: Self) -> BNBaseStructure {
682 BNBaseStructure {
683 type_: unsafe { Ref::into_raw(value.ty) }.handle,
684 offset: value.offset,
685 width: value.width,
686 }
687 }
688
689 pub(crate) fn into_owned_raw(value: &Self) -> BNBaseStructure {
690 BNBaseStructure {
691 type_: value.ty.handle,
692 offset: value.offset,
693 width: value.width,
694 }
695 }
696
697 #[allow(unused)]
698 pub(crate) fn free_raw(value: BNBaseStructure) {
699 let _ = unsafe { NamedTypeReference::ref_from_raw(value.type_) };
700 }
701
702 pub fn new(ty: Ref<NamedTypeReference>, offset: u64, width: u64) -> Self {
703 Self { ty, offset, width }
704 }
705}