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