1#![allow(unused)]
15
16use binaryninjacore_sys::*;
17
18use crate::architecture::Architecture;
19use crate::architecture::CoreArchitecture;
20use crate::basic_block::BasicBlock;
21use crate::function::{Location, NativeBlock};
22use crate::low_level_il as llil;
23use crate::medium_level_il as mlil;
24use crate::string::IntoCStr;
25use crate::string::{raw_to_string, strings_to_string_list, BnString};
26use crate::{high_level_il as hlil, BN_INVALID_EXPR};
27
28use crate::rc::*;
29
30use crate::confidence::MAX_CONFIDENCE;
31use crate::function::{Function, HighlightColor};
32use crate::tags::Tag;
33use crate::types::Type;
34use crate::variable::StackVariableReference;
35
36use crate::binary_view::StringType;
37use crate::high_level_il::HighLevelILFunction;
38use crate::low_level_il::function::{FunctionForm, FunctionMutability, LowLevelILFunction};
39use crate::medium_level_il::MediumLevelILFunction;
40use crate::project::Project;
41use std::convert::From;
42use std::ffi;
43use std::fmt::{Display, Formatter};
44use std::ptr;
45use std::ptr::NonNull;
46
47pub type DisassemblyOption = BNDisassemblyOption;
48pub type InstructionTextTokenType = BNInstructionTextTokenType;
49
50#[derive(Clone, PartialEq, Debug, Default, Eq)]
51pub struct DisassemblyTextLine {
52 pub address: u64,
53 pub instruction_index: usize,
55 pub tokens: Vec<InstructionTextToken>,
56 pub highlight: HighlightColor,
57 pub tags: Vec<Ref<Tag>>,
58 pub type_info: DisassemblyTextLineTypeInfo,
59}
60
61impl DisassemblyTextLine {
62 pub(crate) fn from_raw(value: &BNDisassemblyTextLine) -> Self {
63 let raw_tokens = unsafe { std::slice::from_raw_parts(value.tokens, value.count) };
64 let tokens: Vec<_> = raw_tokens
65 .iter()
66 .map(InstructionTextToken::from_raw)
67 .collect();
68 let raw_tags = unsafe { std::slice::from_raw_parts(value.tags, value.tagCount) };
70 let tags: Vec<_> = raw_tags
71 .iter()
72 .map(|&t| unsafe { Tag::from_raw(t) }.to_owned())
73 .collect();
74 Self {
75 address: value.addr,
76 instruction_index: value.instrIndex,
77 tokens,
78 highlight: value.highlight.into(),
79 tags,
80 type_info: DisassemblyTextLineTypeInfo::from_raw(&value.typeInfo),
81 }
82 }
83
84 pub(crate) fn into_raw(value: Self) -> BNDisassemblyTextLine {
88 let tokens: Box<[BNInstructionTextToken]> = value
90 .tokens
91 .into_iter()
92 .map(InstructionTextToken::into_raw)
93 .collect();
94 let tags: Box<[*mut BNTag]> = value
95 .tags
96 .into_iter()
97 .map(|t| {
98 unsafe { Ref::into_raw(t) }.handle
101 })
102 .collect();
103 BNDisassemblyTextLine {
104 addr: value.address,
105 instrIndex: value.instruction_index,
106 count: tokens.len(),
107 tokens: Box::leak(tokens).as_mut_ptr(),
109 highlight: value.highlight.into(),
110 tagCount: tags.len(),
111 tags: Box::leak(tags).as_mut_ptr(),
113 typeInfo: DisassemblyTextLineTypeInfo::into_raw(value.type_info),
114 }
115 }
116
117 pub(crate) fn free_raw(value: BNDisassemblyTextLine) {
121 let raw_tokens = unsafe { std::slice::from_raw_parts_mut(value.tokens, value.count) };
123 let boxed_tokens = unsafe { Box::from_raw(raw_tokens) };
124 for token in boxed_tokens {
125 InstructionTextToken::free_raw(token);
127 }
128 let raw_tags = unsafe { std::slice::from_raw_parts_mut(value.tags, value.tagCount) };
130 let boxed_tags = unsafe { Box::from_raw(raw_tags) };
131 for tag in boxed_tags {
132 let _ = unsafe { Tag::ref_from_raw(tag) };
134 }
135 DisassemblyTextLineTypeInfo::free_raw(value.typeInfo);
137 }
138
139 pub fn new(tokens: Vec<InstructionTextToken>) -> Self {
140 Self {
141 tokens,
142 ..Default::default()
143 }
144 }
145
146 pub fn new_with_addr(tokens: Vec<InstructionTextToken>, addr: u64) -> Self {
147 Self {
148 address: addr,
149 tokens,
150 ..Default::default()
151 }
152 }
153}
154
155impl From<&str> for DisassemblyTextLine {
156 fn from(value: &str) -> Self {
157 Self::new(vec![InstructionTextToken::new(
158 value,
159 InstructionTextTokenKind::Text,
160 )])
161 }
162}
163
164impl From<String> for DisassemblyTextLine {
165 fn from(value: String) -> Self {
166 Self::new(vec![InstructionTextToken::new(
167 value,
168 InstructionTextTokenKind::Text,
169 )])
170 }
171}
172
173impl Display for DisassemblyTextLine {
174 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175 for token in &self.tokens {
176 write!(f, "{}", token)?;
177 }
178 Ok(())
179 }
180}
181
182impl CoreArrayProvider for DisassemblyTextLine {
183 type Raw = BNDisassemblyTextLine;
184 type Context = ();
185 type Wrapped<'a> = Self;
186}
187
188unsafe impl CoreArrayProviderInner for DisassemblyTextLine {
189 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
190 BNFreeDisassemblyTextLines(raw, count)
191 }
192
193 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
194 Self::from_raw(raw)
195 }
196}
197
198#[derive(Default, Clone, PartialEq, Eq, Debug, Hash)]
199pub struct DisassemblyTextLineTypeInfo {
200 pub has_type_info: bool,
201 pub parent_type: Option<Ref<Type>>,
202 pub field_index: usize,
203 pub offset: u64,
204}
205
206impl DisassemblyTextLineTypeInfo {
207 pub(crate) fn from_raw(value: &BNDisassemblyTextLineTypeInfo) -> Self {
208 Self {
209 has_type_info: value.hasTypeInfo,
210 parent_type: match value.parentType.is_null() {
211 false => Some(unsafe { Type::from_raw(value.parentType).to_owned() }),
212 true => None,
213 },
214 field_index: value.fieldIndex,
215 offset: value.offset,
216 }
217 }
218
219 pub(crate) fn from_owned_raw(value: BNDisassemblyTextLineTypeInfo) -> Self {
220 Self {
221 has_type_info: value.hasTypeInfo,
222 parent_type: match value.parentType.is_null() {
223 false => Some(unsafe { Type::ref_from_raw(value.parentType) }),
224 true => None,
225 },
226 field_index: value.fieldIndex,
227 offset: value.offset,
228 }
229 }
230
231 pub(crate) fn into_raw(value: Self) -> BNDisassemblyTextLineTypeInfo {
232 BNDisassemblyTextLineTypeInfo {
233 hasTypeInfo: value.has_type_info,
234 parentType: value
235 .parent_type
236 .map(|t| unsafe { Ref::into_raw(t) }.handle)
237 .unwrap_or(std::ptr::null_mut()),
238 fieldIndex: value.field_index,
239 offset: value.offset,
240 }
241 }
242
243 pub(crate) fn into_owned_raw(value: &Self) -> BNDisassemblyTextLineTypeInfo {
244 BNDisassemblyTextLineTypeInfo {
245 hasTypeInfo: value.has_type_info,
246 parentType: value
247 .parent_type
248 .as_ref()
249 .map(|t| t.handle)
250 .unwrap_or(std::ptr::null_mut()),
251 fieldIndex: value.field_index,
252 offset: value.offset,
253 }
254 }
255
256 pub(crate) fn free_raw(value: BNDisassemblyTextLineTypeInfo) {
257 if !value.parentType.is_null() {
258 let _ = unsafe { Type::ref_from_raw(value.parentType) };
259 }
260 }
261}
262
263#[derive(Debug, Clone, PartialEq, Eq)]
264pub struct InstructionTextToken {
265 pub address: u64,
266 pub text: String,
267 pub confidence: u8,
268 pub context: InstructionTextTokenContext,
269 pub expr_index: Option<usize>,
270 pub kind: InstructionTextTokenKind,
271}
272
273impl InstructionTextToken {
274 pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
275 Self {
276 address: value.address,
277 text: raw_to_string(value.text).unwrap(),
278 confidence: value.confidence,
279 context: value.context.into(),
280 expr_index: match value.exprIndex {
281 BN_INVALID_EXPR => None,
282 index => Some(index),
283 },
284 kind: InstructionTextTokenKind::from_raw(value),
285 }
286 }
287
288 pub(crate) fn into_raw(value: Self) -> BNInstructionTextToken {
289 let bn_text = BnString::new(value.text);
290 let kind_value = value.kind.try_value().unwrap_or(0);
292 let operand = value.kind.try_operand().unwrap_or(0);
293 let size = value.kind.try_size().unwrap_or(0);
294 let type_names = value.kind.try_type_names().unwrap_or_default();
295 BNInstructionTextToken {
296 type_: value.kind.into(),
297 text: BnString::into_raw(bn_text),
299 value: kind_value,
300 width: 0,
302 size,
303 operand,
304 context: value.context.into(),
305 confidence: value.confidence,
306 address: value.address,
307 typeNames: strings_to_string_list(&type_names),
309 namesCount: type_names.len(),
310 exprIndex: value.expr_index.unwrap_or(BN_INVALID_EXPR),
311 }
312 }
313
314 pub(crate) fn free_raw(value: BNInstructionTextToken) {
315 unsafe { BnString::free_raw(value.text) };
316 if !value.typeNames.is_null() {
317 unsafe { BNFreeStringList(value.typeNames, value.namesCount) };
318 }
319 }
320
321 pub fn new(text: impl Into<String>, kind: InstructionTextTokenKind) -> Self {
326 Self {
327 address: 0,
328 text: text.into(),
329 confidence: MAX_CONFIDENCE,
330 context: InstructionTextTokenContext::Normal,
331 expr_index: None,
332 kind,
333 }
334 }
335
336 pub fn new_with_address(
337 address: u64,
338 text: impl Into<String>,
339 kind: InstructionTextTokenKind,
340 ) -> Self {
341 Self {
342 address,
343 text: text.into(),
344 confidence: MAX_CONFIDENCE,
345 context: InstructionTextTokenContext::Normal,
346 expr_index: None,
347 kind,
348 }
349 }
350}
351
352impl Display for InstructionTextToken {
353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354 self.text.fmt(f)
355 }
356}
357
358impl CoreArrayProvider for InstructionTextToken {
359 type Raw = BNInstructionTextToken;
360 type Context = ();
361 type Wrapped<'a> = Self;
362}
363
364unsafe impl CoreArrayProviderInner for InstructionTextToken {
365 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
366 BNFreeInstructionText(raw, count)
368 }
369
370 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
371 Self::from_raw(raw)
372 }
373}
374
375impl CoreArrayProvider for Array<InstructionTextToken> {
376 type Raw = BNInstructionTextLine;
377 type Context = ();
378 type Wrapped<'a> = std::mem::ManuallyDrop<Self>;
379}
380
381unsafe impl CoreArrayProviderInner for Array<InstructionTextToken> {
382 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
383 BNFreeInstructionTextLines(raw, count)
385 }
386
387 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
388 std::mem::ManuallyDrop::new(Self::new(raw.tokens, raw.count, ()))
390 }
391}
392
393#[derive(Clone, PartialEq, Debug)]
394pub enum InstructionTextTokenKind {
395 Text,
396 Instruction,
397 OperandSeparator,
398 Register,
399 Integer {
400 value: u64,
401 size: Option<usize>,
403 },
404 PossibleAddress {
405 value: u64,
406 size: Option<usize>,
408 },
409 BeginMemoryOperand,
410 EndMemoryOperand,
411 FloatingPoint {
412 value: f64,
413 size: Option<usize>,
415 },
416 Annotation,
417 CodeRelativeAddress {
418 value: u64,
419 size: Option<usize>,
420 },
421 ArgumentName {
422 value: u64,
424 },
425 HexDumpByteValue {
426 value: u8,
427 },
428 HexDumpSkippedByte,
429 HexDumpInvalidByte,
430 HexDumpText {
431 width: u64,
433 },
434 Opcode,
435 String {
436 value: u64,
439 },
440 StringContent {
444 ty: StringType,
445 },
446 CharacterConstant,
447 Keyword {
448 value: u64,
450 },
451 TypeName,
452 FieldName {
453 offset: u64,
455 type_names: Vec<String>,
460 },
461 NameSpace,
462 NameSpaceSeparator,
463 Tag,
464 StructOffset {
465 offset: u64,
467 type_names: Vec<String>,
470 },
471 StructOffsetByteValue,
473 StructureHexDumpText {
475 width: u64,
477 },
478 GotoLabel {
479 target: u64,
480 },
481 Comment {
482 target: u64,
483 },
484 PossibleValue {
485 value: u64,
486 },
487 PossibleValueType,
489 ArrayIndex {
490 index: u64,
491 },
492 Indentation,
493 UnknownMemory,
494 EnumerationMember {
495 value: u64,
496 type_id: Option<String>,
500 },
501 Operation,
503 BaseStructureName,
504 BaseStructureSeparator,
505 Brace {
506 hash: Option<u64>,
508 },
509 ValueLocation,
510 CodeSymbol {
511 value: u64,
513 size: usize, },
516 DataSymbol {
517 value: u64,
519 size: usize, },
522 LocalVariable {
523 variable_id: u64,
527 ssa_version: usize,
529 },
530 Import {
531 target: u64,
533 },
534 AddressDisplay {
535 address: u64,
536 },
537 IndirectImport {
539 target: u64,
543 size: usize,
545 source_operand: usize,
547 },
548 ExternalSymbol {
549 value: u64,
551 },
552 StackVariable {
553 variable_id: u64,
556 },
557 AddressSeparator,
558 CollapsedInformation,
559 CollapseStateIndicator {
560 hash: Option<u64>,
562 },
563 NewLine {
564 value: u64,
566 },
567}
568
569impl InstructionTextTokenKind {
570 pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
571 match value.type_ {
572 BNInstructionTextTokenType::TextToken => Self::Text,
573 BNInstructionTextTokenType::InstructionToken => Self::Instruction,
574 BNInstructionTextTokenType::OperandSeparatorToken => Self::OperandSeparator,
575 BNInstructionTextTokenType::RegisterToken => Self::Register,
576 BNInstructionTextTokenType::IntegerToken => Self::Integer {
577 value: value.value,
578 size: match value.size {
579 0 => None,
580 size => Some(size),
581 },
582 },
583 BNInstructionTextTokenType::PossibleAddressToken => Self::PossibleAddress {
584 value: value.value,
585 size: match value.size {
586 0 => None,
587 size => Some(size),
588 },
589 },
590 BNInstructionTextTokenType::BeginMemoryOperandToken => Self::BeginMemoryOperand,
591 BNInstructionTextTokenType::EndMemoryOperandToken => Self::EndMemoryOperand,
592 BNInstructionTextTokenType::FloatingPointToken => Self::FloatingPoint {
593 value: value.value as f64,
594 size: match value.size {
595 0 => None,
596 size => Some(size),
597 },
598 },
599 BNInstructionTextTokenType::AnnotationToken => Self::Annotation,
600 BNInstructionTextTokenType::CodeRelativeAddressToken => Self::CodeRelativeAddress {
601 value: value.value,
602 size: match value.size {
603 0 => None,
604 size => Some(size),
605 },
606 },
607 BNInstructionTextTokenType::ArgumentNameToken => {
608 Self::ArgumentName { value: value.value }
609 }
610 BNInstructionTextTokenType::HexDumpByteValueToken => Self::HexDumpByteValue {
611 value: value.value as u8,
612 },
613 BNInstructionTextTokenType::HexDumpSkippedByteToken => Self::HexDumpSkippedByte,
614 BNInstructionTextTokenType::HexDumpInvalidByteToken => Self::HexDumpInvalidByte,
615 BNInstructionTextTokenType::HexDumpTextToken => {
616 Self::HexDumpText { width: value.value }
617 }
618 BNInstructionTextTokenType::OpcodeToken => Self::Opcode,
619 BNInstructionTextTokenType::StringToken => match value.context {
620 BNInstructionTextTokenContext::StringReferenceTokenContext
621 | BNInstructionTextTokenContext::StringDisplayTokenContext => {
622 match value.value {
623 0 => Self::StringContent {
624 ty: StringType::AsciiString,
625 },
626 1 => Self::StringContent {
627 ty: StringType::Utf8String,
628 },
629 2 => Self::StringContent {
630 ty: StringType::Utf16String,
631 },
632 3 => Self::StringContent {
633 ty: StringType::Utf32String,
634 },
635 value => Self::String { value },
639 }
640 }
641 _ => Self::String { value: value.value },
642 },
643 BNInstructionTextTokenType::CharacterConstantToken => Self::CharacterConstant,
644 BNInstructionTextTokenType::KeywordToken => Self::Keyword { value: value.value },
645 BNInstructionTextTokenType::TypeNameToken => Self::TypeName,
646 BNInstructionTextTokenType::FieldNameToken => Self::FieldName {
647 offset: value.value,
648 type_names: {
649 let raw_names =
651 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
652 raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
653 },
654 },
655 BNInstructionTextTokenType::NameSpaceToken => Self::NameSpace,
656 BNInstructionTextTokenType::NameSpaceSeparatorToken => Self::NameSpaceSeparator,
657 BNInstructionTextTokenType::TagToken => Self::Tag,
658 BNInstructionTextTokenType::StructOffsetToken => Self::StructOffset {
659 offset: value.value,
660 type_names: {
661 let raw_names =
663 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
664 raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
665 },
666 },
667 BNInstructionTextTokenType::StructOffsetByteValueToken => Self::StructOffsetByteValue,
668 BNInstructionTextTokenType::StructureHexDumpTextToken => {
669 Self::StructureHexDumpText { width: value.value }
670 }
671 BNInstructionTextTokenType::GotoLabelToken => Self::GotoLabel {
672 target: value.value,
673 },
674 BNInstructionTextTokenType::CommentToken => Self::Comment {
675 target: value.value,
676 },
677 BNInstructionTextTokenType::PossibleValueToken => {
678 Self::PossibleValue { value: value.value }
679 }
680 BNInstructionTextTokenType::PossibleValueTypeToken => Self::PossibleValueType,
682 BNInstructionTextTokenType::ArrayIndexToken => Self::ArrayIndex { index: value.value },
683 BNInstructionTextTokenType::IndentationToken => Self::Indentation,
684 BNInstructionTextTokenType::UnknownMemoryToken => Self::UnknownMemory,
685 BNInstructionTextTokenType::EnumerationMemberToken => Self::EnumerationMember {
686 value: value.value,
687 type_id: {
688 let raw_names =
691 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
692 raw_names.iter().filter_map(|&r| raw_to_string(r)).next()
693 },
694 },
695 BNInstructionTextTokenType::OperationToken => Self::Operation,
696 BNInstructionTextTokenType::BaseStructureNameToken => Self::BaseStructureName,
697 BNInstructionTextTokenType::BaseStructureSeparatorToken => Self::BaseStructureSeparator,
698 BNInstructionTextTokenType::BraceToken => Self::Brace {
699 hash: match value.value {
700 0 => None,
701 hash => Some(hash),
702 },
703 },
704 BNInstructionTextTokenType::ValueLocationToken => Self::ValueLocation,
705 BNInstructionTextTokenType::CodeSymbolToken => Self::CodeSymbol {
706 value: value.value,
707 size: value.size,
708 },
709 BNInstructionTextTokenType::DataSymbolToken => Self::DataSymbol {
710 value: value.value,
711 size: value.size,
712 },
713 BNInstructionTextTokenType::LocalVariableToken => Self::LocalVariable {
714 variable_id: value.value,
715 ssa_version: value.operand,
716 },
717 BNInstructionTextTokenType::ImportToken => Self::Import {
718 target: value.value,
719 },
720 BNInstructionTextTokenType::AddressDisplayToken => Self::AddressDisplay {
721 address: value.value,
722 },
723 BNInstructionTextTokenType::IndirectImportToken => Self::IndirectImport {
724 target: value.value,
725 size: value.size,
726 source_operand: value.operand,
727 },
728 BNInstructionTextTokenType::ExternalSymbolToken => {
729 Self::ExternalSymbol { value: value.value }
730 }
731 BNInstructionTextTokenType::StackVariableToken => Self::StackVariable {
732 variable_id: value.value,
733 },
734 BNInstructionTextTokenType::AddressSeparatorToken => Self::AddressSeparator,
735 BNInstructionTextTokenType::CollapsedInformationToken => Self::CollapsedInformation,
736 BNInstructionTextTokenType::CollapseStateIndicatorToken => {
737 Self::CollapseStateIndicator {
738 hash: match value.value {
739 0 => None,
740 hash => Some(hash),
741 },
742 }
743 }
744 BNInstructionTextTokenType::NewLineToken => Self::NewLine { value: value.value },
745 }
746 }
747
748 fn try_value(&self) -> Option<u64> {
750 match self {
752 InstructionTextTokenKind::Integer { value, .. } => Some(*value),
753 InstructionTextTokenKind::PossibleAddress { value, .. } => Some(*value),
754 InstructionTextTokenKind::PossibleValue { value, .. } => Some(*value),
755 InstructionTextTokenKind::FloatingPoint { value, .. } => Some(*value as u64),
756 InstructionTextTokenKind::CodeRelativeAddress { value, .. } => Some(*value),
757 InstructionTextTokenKind::ArgumentName { value, .. } => Some(*value),
758 InstructionTextTokenKind::HexDumpByteValue { value, .. } => Some(*value as u64),
759 InstructionTextTokenKind::HexDumpText { width, .. } => Some(*width),
760 InstructionTextTokenKind::String { value, .. } => Some(*value),
761 InstructionTextTokenKind::StringContent { ty, .. } => Some(*ty as u64),
762 InstructionTextTokenKind::Keyword { value, .. } => Some(*value),
763 InstructionTextTokenKind::FieldName { offset, .. } => Some(*offset),
764 InstructionTextTokenKind::StructOffset { offset, .. } => Some(*offset),
765 InstructionTextTokenKind::StructureHexDumpText { width, .. } => Some(*width),
766 InstructionTextTokenKind::GotoLabel { target, .. } => Some(*target),
767 InstructionTextTokenKind::Comment { target, .. } => Some(*target),
768 InstructionTextTokenKind::ArrayIndex { index, .. } => Some(*index),
769 InstructionTextTokenKind::EnumerationMember { value, .. } => Some(*value),
770 InstructionTextTokenKind::LocalVariable { variable_id, .. } => Some(*variable_id),
771 InstructionTextTokenKind::Import { target, .. } => Some(*target),
772 InstructionTextTokenKind::AddressDisplay { address, .. } => Some(*address),
773 InstructionTextTokenKind::IndirectImport { target, .. } => Some(*target),
774 InstructionTextTokenKind::Brace { hash, .. } => *hash,
775 InstructionTextTokenKind::CodeSymbol { value, .. } => Some(*value),
776 InstructionTextTokenKind::DataSymbol { value, .. } => Some(*value),
777 InstructionTextTokenKind::ExternalSymbol { value, .. } => Some(*value),
778 InstructionTextTokenKind::StackVariable { variable_id, .. } => Some(*variable_id),
779 InstructionTextTokenKind::CollapseStateIndicator { hash, .. } => *hash,
780 InstructionTextTokenKind::NewLine { value, .. } => Some(*value),
781 _ => None,
782 }
783 }
784
785 fn try_size(&self) -> Option<usize> {
787 match self {
788 InstructionTextTokenKind::Integer { size, .. } => *size,
789 InstructionTextTokenKind::FloatingPoint { size, .. } => *size,
790 InstructionTextTokenKind::PossibleAddress { size, .. } => *size,
791 InstructionTextTokenKind::CodeRelativeAddress { size, .. } => *size,
792 InstructionTextTokenKind::CodeSymbol { size, .. } => Some(*size),
793 InstructionTextTokenKind::DataSymbol { size, .. } => Some(*size),
794 InstructionTextTokenKind::IndirectImport { size, .. } => Some(*size),
795 _ => None,
796 }
797 }
798
799 fn try_operand(&self) -> Option<usize> {
801 match self {
802 InstructionTextTokenKind::LocalVariable { ssa_version, .. } => Some(*ssa_version),
803 InstructionTextTokenKind::IndirectImport { source_operand, .. } => {
804 Some(*source_operand)
805 }
806 _ => None,
807 }
808 }
809
810 fn try_type_names(&self) -> Option<Vec<String>> {
812 match self {
813 InstructionTextTokenKind::FieldName { type_names, .. } => Some(type_names.clone()),
814 InstructionTextTokenKind::StructOffset { type_names, .. } => Some(type_names.clone()),
815 InstructionTextTokenKind::EnumerationMember { type_id, .. } => {
816 Some(vec![type_id.clone()?])
817 }
818 _ => None,
819 }
820 }
821}
822
823impl From<InstructionTextTokenKind> for BNInstructionTextTokenType {
824 fn from(value: InstructionTextTokenKind) -> Self {
825 match value {
826 InstructionTextTokenKind::Text => BNInstructionTextTokenType::TextToken,
827 InstructionTextTokenKind::Instruction => BNInstructionTextTokenType::InstructionToken,
828 InstructionTextTokenKind::OperandSeparator => {
829 BNInstructionTextTokenType::OperandSeparatorToken
830 }
831 InstructionTextTokenKind::Register => BNInstructionTextTokenType::RegisterToken,
832 InstructionTextTokenKind::Integer { .. } => BNInstructionTextTokenType::IntegerToken,
833 InstructionTextTokenKind::PossibleAddress { .. } => {
834 BNInstructionTextTokenType::PossibleAddressToken
835 }
836 InstructionTextTokenKind::BeginMemoryOperand => {
837 BNInstructionTextTokenType::BeginMemoryOperandToken
838 }
839 InstructionTextTokenKind::EndMemoryOperand => {
840 BNInstructionTextTokenType::EndMemoryOperandToken
841 }
842 InstructionTextTokenKind::FloatingPoint { .. } => {
843 BNInstructionTextTokenType::FloatingPointToken
844 }
845 InstructionTextTokenKind::Annotation => BNInstructionTextTokenType::AnnotationToken,
846 InstructionTextTokenKind::CodeRelativeAddress { .. } => {
847 BNInstructionTextTokenType::CodeRelativeAddressToken
848 }
849 InstructionTextTokenKind::ArgumentName { .. } => {
850 BNInstructionTextTokenType::ArgumentNameToken
851 }
852 InstructionTextTokenKind::HexDumpByteValue { .. } => {
853 BNInstructionTextTokenType::HexDumpByteValueToken
854 }
855 InstructionTextTokenKind::HexDumpSkippedByte => {
856 BNInstructionTextTokenType::HexDumpSkippedByteToken
857 }
858 InstructionTextTokenKind::HexDumpInvalidByte => {
859 BNInstructionTextTokenType::HexDumpInvalidByteToken
860 }
861 InstructionTextTokenKind::HexDumpText { .. } => {
862 BNInstructionTextTokenType::HexDumpTextToken
863 }
864 InstructionTextTokenKind::Opcode => BNInstructionTextTokenType::OpcodeToken,
865 InstructionTextTokenKind::String { .. } => BNInstructionTextTokenType::StringToken,
866 InstructionTextTokenKind::StringContent { .. } => {
867 BNInstructionTextTokenType::StringToken
868 }
869 InstructionTextTokenKind::CharacterConstant => {
870 BNInstructionTextTokenType::CharacterConstantToken
871 }
872 InstructionTextTokenKind::Keyword { .. } => BNInstructionTextTokenType::KeywordToken,
873 InstructionTextTokenKind::TypeName => BNInstructionTextTokenType::TypeNameToken,
874 InstructionTextTokenKind::FieldName { .. } => {
875 BNInstructionTextTokenType::FieldNameToken
876 }
877 InstructionTextTokenKind::NameSpace => BNInstructionTextTokenType::NameSpaceToken,
878 InstructionTextTokenKind::NameSpaceSeparator => {
879 BNInstructionTextTokenType::NameSpaceSeparatorToken
880 }
881 InstructionTextTokenKind::Tag => BNInstructionTextTokenType::TagToken,
882 InstructionTextTokenKind::StructOffset { .. } => {
883 BNInstructionTextTokenType::StructOffsetToken
884 }
885 InstructionTextTokenKind::StructOffsetByteValue => {
886 BNInstructionTextTokenType::StructOffsetByteValueToken
887 }
888 InstructionTextTokenKind::StructureHexDumpText { .. } => {
889 BNInstructionTextTokenType::StructureHexDumpTextToken
890 }
891 InstructionTextTokenKind::GotoLabel { .. } => {
892 BNInstructionTextTokenType::GotoLabelToken
893 }
894 InstructionTextTokenKind::Comment { .. } => BNInstructionTextTokenType::CommentToken,
895 InstructionTextTokenKind::PossibleValue { .. } => {
896 BNInstructionTextTokenType::PossibleValueToken
897 }
898 InstructionTextTokenKind::PossibleValueType => {
899 BNInstructionTextTokenType::PossibleValueTypeToken
900 }
901 InstructionTextTokenKind::ArrayIndex { .. } => {
902 BNInstructionTextTokenType::ArrayIndexToken
903 }
904 InstructionTextTokenKind::Indentation => BNInstructionTextTokenType::IndentationToken,
905 InstructionTextTokenKind::UnknownMemory => {
906 BNInstructionTextTokenType::UnknownMemoryToken
907 }
908 InstructionTextTokenKind::EnumerationMember { .. } => {
909 BNInstructionTextTokenType::EnumerationMemberToken
910 }
911 InstructionTextTokenKind::Operation => BNInstructionTextTokenType::OperationToken,
912 InstructionTextTokenKind::BaseStructureName => {
913 BNInstructionTextTokenType::BaseStructureNameToken
914 }
915 InstructionTextTokenKind::BaseStructureSeparator => {
916 BNInstructionTextTokenType::BaseStructureSeparatorToken
917 }
918 InstructionTextTokenKind::Brace { .. } => BNInstructionTextTokenType::BraceToken,
919 InstructionTextTokenKind::ValueLocation => {
920 BNInstructionTextTokenType::ValueLocationToken
921 }
922 InstructionTextTokenKind::CodeSymbol { .. } => {
923 BNInstructionTextTokenType::CodeSymbolToken
924 }
925 InstructionTextTokenKind::DataSymbol { .. } => {
926 BNInstructionTextTokenType::DataSymbolToken
927 }
928 InstructionTextTokenKind::LocalVariable { .. } => {
929 BNInstructionTextTokenType::LocalVariableToken
930 }
931 InstructionTextTokenKind::Import { .. } => BNInstructionTextTokenType::ImportToken,
932 InstructionTextTokenKind::AddressDisplay { .. } => {
933 BNInstructionTextTokenType::AddressDisplayToken
934 }
935 InstructionTextTokenKind::IndirectImport { .. } => {
936 BNInstructionTextTokenType::IndirectImportToken
937 }
938 InstructionTextTokenKind::ExternalSymbol { .. } => {
939 BNInstructionTextTokenType::ExternalSymbolToken
940 }
941 InstructionTextTokenKind::StackVariable { .. } => {
942 BNInstructionTextTokenType::StackVariableToken
943 }
944 InstructionTextTokenKind::AddressSeparator => {
945 BNInstructionTextTokenType::AddressSeparatorToken
946 }
947 InstructionTextTokenKind::CollapsedInformation => {
948 BNInstructionTextTokenType::CollapsedInformationToken
949 }
950 InstructionTextTokenKind::CollapseStateIndicator { .. } => {
951 BNInstructionTextTokenType::CollapseStateIndicatorToken
952 }
953 InstructionTextTokenKind::NewLine { .. } => BNInstructionTextTokenType::NewLineToken,
954 }
955 }
956}
957
958impl Eq for InstructionTextTokenKind {}
959
960#[derive(Clone, Copy, PartialEq, Eq, Debug)]
961pub enum InstructionTextTokenContext {
962 Normal,
963 LocalVariable,
964 DataVariable,
965 FunctionReturn,
966 InstructionAddress,
967 ILInstructionIndex,
968 ConstData,
969 ConstStringData,
971 StringReference,
973 StringDataVariable,
975 StringDisplay,
979 Collapsed,
981 Expanded,
983 CollapsiblePadding,
985 DerivedStringReference,
987}
988
989impl From<BNInstructionTextTokenContext> for InstructionTextTokenContext {
990 fn from(value: BNInstructionTextTokenContext) -> Self {
991 match value {
992 BNInstructionTextTokenContext::NoTokenContext => Self::Normal,
993 BNInstructionTextTokenContext::LocalVariableTokenContext => Self::LocalVariable,
994 BNInstructionTextTokenContext::DataVariableTokenContext => Self::DataVariable,
995 BNInstructionTextTokenContext::FunctionReturnTokenContext => Self::FunctionReturn,
996 BNInstructionTextTokenContext::InstructionAddressTokenContext => {
997 Self::InstructionAddress
998 }
999 BNInstructionTextTokenContext::ILInstructionIndexTokenContext => {
1000 Self::ILInstructionIndex
1001 }
1002 BNInstructionTextTokenContext::ConstDataTokenContext => Self::ConstData,
1003 BNInstructionTextTokenContext::ConstStringDataTokenContext => Self::ConstStringData,
1005 BNInstructionTextTokenContext::StringReferenceTokenContext => Self::StringReference,
1006 BNInstructionTextTokenContext::StringDataVariableTokenContext => {
1007 Self::StringDataVariable
1008 }
1009 BNInstructionTextTokenContext::StringDisplayTokenContext => Self::StringDisplay,
1010 BNInstructionTextTokenContext::ContentCollapsedContext => Self::Collapsed,
1012 BNInstructionTextTokenContext::ContentExpandedContext => Self::Expanded,
1013 BNInstructionTextTokenContext::ContentCollapsiblePadding => Self::CollapsiblePadding,
1014 BNInstructionTextTokenContext::DerivedStringReferenceTokenContext => {
1015 Self::DerivedStringReference
1016 }
1017 }
1018 }
1019}
1020
1021impl From<InstructionTextTokenContext> for BNInstructionTextTokenContext {
1022 fn from(value: InstructionTextTokenContext) -> Self {
1023 match value {
1024 InstructionTextTokenContext::Normal => Self::NoTokenContext,
1025 InstructionTextTokenContext::LocalVariable => Self::LocalVariableTokenContext,
1026 InstructionTextTokenContext::DataVariable => Self::DataVariableTokenContext,
1027 InstructionTextTokenContext::FunctionReturn => Self::FunctionReturnTokenContext,
1028 InstructionTextTokenContext::InstructionAddress => Self::InstructionAddressTokenContext,
1029 InstructionTextTokenContext::ILInstructionIndex => Self::ILInstructionIndexTokenContext,
1030 InstructionTextTokenContext::ConstData => Self::ConstDataTokenContext,
1031 InstructionTextTokenContext::ConstStringData => Self::ConstStringDataTokenContext,
1032 InstructionTextTokenContext::StringReference => Self::StringReferenceTokenContext,
1033 InstructionTextTokenContext::StringDataVariable => Self::StringDataVariableTokenContext,
1034 InstructionTextTokenContext::StringDisplay => Self::StringDisplayTokenContext,
1035 InstructionTextTokenContext::Collapsed => Self::ContentCollapsedContext,
1036 InstructionTextTokenContext::Expanded => Self::ContentExpandedContext,
1037 InstructionTextTokenContext::CollapsiblePadding => Self::ContentCollapsiblePadding,
1038 InstructionTextTokenContext::DerivedStringReference => {
1039 Self::DerivedStringReferenceTokenContext
1040 }
1041 }
1042 }
1043}
1044
1045#[repr(transparent)]
1046pub struct DisassemblyTextRenderer {
1047 handle: NonNull<BNDisassemblyTextRenderer>,
1048}
1049
1050impl DisassemblyTextRenderer {
1051 pub unsafe fn ref_from_raw(handle: NonNull<BNDisassemblyTextRenderer>) -> Ref<Self> {
1052 Ref::new(Self { handle })
1053 }
1054
1055 pub fn from_function(func: &Function, settings: Option<&DisassemblySettings>) -> Ref<Self> {
1056 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1057 let result = unsafe { BNCreateDisassemblyTextRenderer(func.handle, settings_ptr) };
1058 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1059 }
1060
1061 pub fn from_llil<M: FunctionMutability, F: FunctionForm>(
1062 func: &LowLevelILFunction<M, F>,
1063 settings: Option<&DisassemblySettings>,
1064 ) -> Ref<Self> {
1065 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1066 let result =
1067 unsafe { BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1068 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1069 }
1070
1071 pub fn from_mlil(
1072 func: &MediumLevelILFunction,
1073 settings: Option<&DisassemblySettings>,
1074 ) -> Ref<Self> {
1075 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1076 let result =
1077 unsafe { BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1078 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1079 }
1080
1081 pub fn from_hlil(
1082 func: &HighLevelILFunction,
1083 settings: Option<&DisassemblySettings>,
1084 ) -> Ref<Self> {
1085 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1086 let result =
1087 unsafe { BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1088 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1089 }
1090
1091 pub fn function(&self) -> Ref<Function> {
1092 let result = unsafe { BNGetDisassemblyTextRendererFunction(self.handle.as_ptr()) };
1093 assert!(!result.is_null());
1094 unsafe { Function::ref_from_raw(result) }
1095 }
1096
1097 pub fn llil<M: FunctionMutability, F: FunctionForm>(&self) -> Ref<LowLevelILFunction<M, F>> {
1098 let result =
1099 unsafe { BNGetDisassemblyTextRendererLowLevelILFunction(self.handle.as_ptr()) };
1100 assert!(!result.is_null());
1101 unsafe { LowLevelILFunction::ref_from_raw(result) }
1102 }
1103
1104 pub fn mlil(&self) -> Ref<MediumLevelILFunction> {
1105 let result =
1106 unsafe { BNGetDisassemblyTextRendererMediumLevelILFunction(self.handle.as_ptr()) };
1107 assert!(!result.is_null());
1108 unsafe { MediumLevelILFunction::ref_from_raw(result) }
1109 }
1110
1111 pub fn hlil(&self) -> Ref<HighLevelILFunction> {
1112 let result =
1113 unsafe { BNGetDisassemblyTextRendererHighLevelILFunction(self.handle.as_ptr()) };
1114 assert!(!result.is_null());
1115 unsafe { HighLevelILFunction::ref_from_raw(result, true) }
1116 }
1117
1118 pub fn basic_block(&self) -> Option<Ref<BasicBlock<NativeBlock>>> {
1119 let result = unsafe { BNGetDisassemblyTextRendererBasicBlock(self.handle.as_ptr()) };
1120 if result.is_null() {
1121 return None;
1122 }
1123 Some(unsafe { Ref::new(BasicBlock::from_raw(result, NativeBlock::new())) })
1124 }
1125
1126 pub fn set_basic_block(&self, value: Option<&BasicBlock<NativeBlock>>) {
1127 let block_ptr = value.map(|b| b.handle).unwrap_or(ptr::null_mut());
1128 unsafe { BNSetDisassemblyTextRendererBasicBlock(self.handle.as_ptr(), block_ptr) }
1129 }
1130
1131 pub fn arch(&self) -> CoreArchitecture {
1132 let result = unsafe { BNGetDisassemblyTextRendererArchitecture(self.handle.as_ptr()) };
1133 assert!(!result.is_null());
1134 unsafe { CoreArchitecture::from_raw(result) }
1135 }
1136
1137 pub fn set_arch(&self, value: CoreArchitecture) {
1138 unsafe { BNSetDisassemblyTextRendererArchitecture(self.handle.as_ptr(), value.handle) }
1139 }
1140
1141 pub fn settings(&self) -> Ref<DisassemblySettings> {
1142 let result = unsafe { BNGetDisassemblyTextRendererSettings(self.handle.as_ptr()) };
1143 unsafe { DisassemblySettings::ref_from_raw(result) }
1144 }
1145
1146 pub fn set_settings(&self, settings: Option<&DisassemblySettings>) {
1147 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1148 unsafe { BNSetDisassemblyTextRendererSettings(self.handle.as_ptr(), settings_ptr) }
1149 }
1150
1151 pub fn is_il(&self) -> bool {
1152 unsafe { BNIsILDisassemblyTextRenderer(self.handle.as_ptr()) }
1153 }
1154
1155 pub fn has_data_flow(&self) -> bool {
1156 unsafe { BNDisassemblyTextRendererHasDataFlow(self.handle.as_ptr()) }
1157 }
1158
1159 pub fn instruction_annotations(&self, addr: u64) -> Array<InstructionTextToken> {
1161 let mut count = 0;
1162 let result = unsafe {
1163 BNGetDisassemblyTextRendererInstructionAnnotations(
1164 self.handle.as_ptr(),
1165 addr,
1166 &mut count,
1167 )
1168 };
1169 assert!(!result.is_null());
1170 unsafe { Array::new(result, count, ()) }
1171 }
1172
1173 pub fn instruction_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1175 let mut count = 0;
1176 let mut length = 0;
1177 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1178 let result = unsafe {
1179 BNGetDisassemblyTextRendererInstructionText(
1180 self.handle.as_ptr(),
1181 addr,
1182 &mut length,
1183 &mut lines,
1184 &mut count,
1185 )
1186 };
1187 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1188 }
1189
1190 pub fn disassembly_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1192 let mut count = 0;
1193 let mut length = 0;
1194 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1195 let result = unsafe {
1196 BNGetDisassemblyTextRendererLines(
1197 self.handle.as_ptr(),
1198 addr,
1199 &mut length,
1200 &mut lines,
1201 &mut count,
1202 )
1203 };
1204 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1205 }
1206
1207 pub fn is_integer_token(token_type: InstructionTextTokenType) -> bool {
1210 unsafe { BNIsIntegerToken(token_type) }
1211 }
1212
1213 pub fn reset_deduplicated_comments(&self) {
1214 unsafe { BNResetDisassemblyTextRendererDeduplicatedComments(self.handle.as_ptr()) }
1215 }
1216
1217 pub fn symbol_tokens(
1218 &self,
1219 addr: u64,
1220 size: usize,
1221 operand: Option<usize>,
1222 ) -> Option<Array<InstructionTextToken>> {
1223 let operand = operand.unwrap_or(0xffffffff);
1224 let mut count = 0;
1225 let mut tokens: *mut BNInstructionTextToken = ptr::null_mut();
1226 let result = unsafe {
1227 BNGetDisassemblyTextRendererSymbolTokens(
1228 self.handle.as_ptr(),
1229 addr,
1230 size,
1231 operand,
1232 &mut tokens,
1233 &mut count,
1234 )
1235 };
1236 result.then(|| unsafe { Array::new(tokens, count, ()) })
1237 }
1238
1239 pub fn stack_var_reference_tokens(
1240 &self,
1241 stack_ref: StackVariableReference,
1242 ) -> Array<InstructionTextToken> {
1243 let mut stack_ref_raw = StackVariableReference::into_raw(stack_ref);
1244 let mut count = 0;
1245 let tokens = unsafe {
1246 BNGetDisassemblyTextRendererStackVariableReferenceTokens(
1247 self.handle.as_ptr(),
1248 &mut stack_ref_raw,
1249 &mut count,
1250 )
1251 };
1252 StackVariableReference::free_raw(stack_ref_raw);
1253 assert!(!tokens.is_null());
1254 unsafe { Array::new(tokens, count, ()) }
1255 }
1256
1257 pub fn integer_token(
1258 &self,
1259 int_token: InstructionTextToken,
1260 location: impl Into<Location>,
1261 ) -> Array<InstructionTextToken> {
1262 let location = location.into();
1263 let arch = location
1264 .arch
1265 .map(|a| a.handle)
1266 .unwrap_or_else(std::ptr::null_mut);
1267 let mut count = 0;
1268 let mut int_token_raw = InstructionTextToken::into_raw(int_token);
1269 let tokens = unsafe {
1270 BNGetDisassemblyTextRendererIntegerTokens(
1271 self.handle.as_ptr(),
1272 &mut int_token_raw,
1273 arch,
1274 location.addr,
1275 &mut count,
1276 )
1277 };
1278 InstructionTextToken::free_raw(int_token_raw);
1279 assert!(!tokens.is_null());
1280 unsafe { Array::new(tokens, count, ()) }
1281 }
1282
1283 pub fn wrap_comment(
1284 &self,
1285 cur_line: DisassemblyTextLine,
1286 comment: &str,
1287 has_auto_annotations: bool,
1288 leading_spaces: &str,
1289 indent_spaces: &str,
1290 ) -> Array<DisassemblyTextLine> {
1291 let cur_line_raw = DisassemblyTextLine::into_raw(cur_line);
1292 let comment_raw = comment.to_cstr();
1293 let leading_spaces_raw = leading_spaces.to_cstr();
1294 let indent_spaces_raw = indent_spaces.to_cstr();
1295 let mut count = 0;
1296 let lines = unsafe {
1297 BNDisassemblyTextRendererWrapComment(
1298 self.handle.as_ptr(),
1299 &cur_line_raw,
1300 &mut count,
1301 comment_raw.as_ref().as_ptr() as *const ffi::c_char,
1302 has_auto_annotations,
1303 leading_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1304 indent_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1305 )
1306 };
1307 DisassemblyTextLine::free_raw(cur_line_raw);
1308 assert!(!lines.is_null());
1309 unsafe { Array::new(lines, count, ()) }
1310 }
1311}
1312
1313impl ToOwned for DisassemblyTextRenderer {
1314 type Owned = Ref<Self>;
1315
1316 fn to_owned(&self) -> Self::Owned {
1317 unsafe { RefCountable::inc_ref(self) }
1318 }
1319}
1320
1321unsafe impl RefCountable for DisassemblyTextRenderer {
1322 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1323 Ref::new(Self {
1324 handle: NonNull::new(BNNewDisassemblyTextRendererReference(
1325 handle.handle.as_ptr(),
1326 ))
1327 .unwrap(),
1328 })
1329 }
1330
1331 unsafe fn dec_ref(handle: &Self) {
1332 BNFreeDisassemblyTextRenderer(handle.handle.as_ptr());
1333 }
1334}
1335
1336#[derive(PartialEq, Eq, Hash)]
1338pub struct DisassemblySettings {
1339 pub(crate) handle: *mut BNDisassemblySettings,
1340}
1341
1342impl DisassemblySettings {
1343 pub fn ref_from_raw(handle: *mut BNDisassemblySettings) -> Ref<Self> {
1344 debug_assert!(!handle.is_null());
1345 unsafe { Ref::new(Self { handle }) }
1346 }
1347
1348 pub fn new() -> Ref<Self> {
1349 let handle = unsafe { BNCreateDisassemblySettings() };
1350 Self::ref_from_raw(handle)
1351 }
1352
1353 pub fn set_option(&self, option: DisassemblyOption, state: bool) {
1354 unsafe { BNSetDisassemblySettingsOption(self.handle, option, state) }
1355 }
1356
1357 pub fn is_option_set(&self, option: DisassemblyOption) -> bool {
1358 unsafe { BNIsDisassemblySettingsOptionSet(self.handle, option) }
1359 }
1360}
1361
1362impl ToOwned for DisassemblySettings {
1363 type Owned = Ref<Self>;
1364
1365 fn to_owned(&self) -> Self::Owned {
1366 unsafe { RefCountable::inc_ref(self) }
1367 }
1368}
1369
1370unsafe impl RefCountable for DisassemblySettings {
1371 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1372 Ref::new(Self {
1373 handle: BNNewDisassemblySettingsReference(handle.handle),
1374 })
1375 }
1376
1377 unsafe fn dec_ref(handle: &Self) {
1378 BNFreeDisassemblySettings(handle.handle);
1379 }
1380}