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,
401 Register,
402 Integer {
403 value: u64,
404 size: Option<usize>,
406 operand: Option<usize>,
413 },
414 PossibleAddress {
415 value: u64,
416 size: Option<usize>,
418 operand: Option<usize>,
425 },
426 BeginMemoryOperand,
427 EndMemoryOperand,
428 FloatingPoint {
429 value: f64,
430 size: Option<usize>,
432 },
433 Annotation,
434 CodeRelativeAddress {
435 value: u64,
436 size: Option<usize>,
438 operand: Option<usize>,
445 },
446 ArgumentName {
447 value: u64,
449 },
450 HexDumpByteValue {
451 value: u8,
452 },
453 HexDumpSkippedByte,
454 HexDumpInvalidByte,
455 HexDumpText {
456 width: u64,
458 },
459 Opcode,
460 String {
461 value: u64,
464 },
465 StringContent {
469 ty: StringType,
470 },
471 CharacterConstant {
472 operand: Option<usize>,
479 },
480 Keyword {
481 value: u64,
483 },
484 TypeName,
485 FieldName {
486 offset: u64,
488 type_names: Vec<String>,
493 },
494 NameSpace,
495 NameSpaceSeparator,
496 Tag,
497 StructOffset {
498 offset: u64,
500 type_names: Vec<String>,
503 },
504 StructOffsetByteValue,
506 StructureHexDumpText {
508 width: u64,
510 },
511 GotoLabel {
512 target: u64,
513 },
514 Comment {
515 target: u64,
516 },
517 PossibleValue {
518 value: u64,
519 },
520 PossibleValueType,
522 ArrayIndex {
523 index: u64,
524 },
525 Indentation,
526 UnknownMemory,
527 EnumerationMember {
528 value: u64,
529 type_id: Option<String>,
533 },
534 Operation,
536 BaseStructureName,
537 BaseStructureSeparator,
538 Brace {
539 hash: Option<u64>,
541 },
542 ValueLocation,
543 CodeSymbol {
544 value: u64,
546 size: usize, },
549 DataSymbol {
550 value: u64,
552 size: usize, },
555 LocalVariable {
556 variable_id: u64,
560 ssa_version: usize,
562 },
563 Import {
564 target: u64,
566 },
567 AddressDisplay {
568 address: u64,
569 },
570 IndirectImport {
572 target: u64,
576 size: usize,
578 source_operand: usize,
580 },
581 ExternalSymbol {
582 value: u64,
584 },
585 StackVariable {
586 variable_id: u64,
589 },
590 AddressSeparator,
591 CollapsedInformation,
592 CollapseStateIndicator {
593 hash: Option<u64>,
595 },
596 NewLine {
597 value: u64,
599 },
600}
601
602impl InstructionTextTokenKind {
603 pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
604 match value.type_ {
605 BNInstructionTextTokenType::TextToken => Self::Text,
606 BNInstructionTextTokenType::InstructionToken => Self::Instruction,
607 BNInstructionTextTokenType::OperandSeparatorToken => Self::OperandSeparator,
608 BNInstructionTextTokenType::RegisterToken => Self::Register,
609 BNInstructionTextTokenType::IntegerToken => Self::Integer {
610 value: value.value,
611 size: match value.size {
612 0 => None,
613 size => Some(size),
614 },
615 operand: Some(value.operand),
616 },
617 BNInstructionTextTokenType::PossibleAddressToken => Self::PossibleAddress {
618 value: value.value,
619 size: match value.size {
620 0 => None,
621 size => Some(size),
622 },
623 operand: Some(value.operand),
624 },
625 BNInstructionTextTokenType::BeginMemoryOperandToken => Self::BeginMemoryOperand,
626 BNInstructionTextTokenType::EndMemoryOperandToken => Self::EndMemoryOperand,
627 BNInstructionTextTokenType::FloatingPointToken => Self::FloatingPoint {
628 value: value.value as f64,
629 size: match value.size {
630 0 => None,
631 size => Some(size),
632 },
633 },
634 BNInstructionTextTokenType::AnnotationToken => Self::Annotation,
635 BNInstructionTextTokenType::CodeRelativeAddressToken => Self::CodeRelativeAddress {
636 value: value.value,
637 size: match value.size {
638 0 => None,
639 size => Some(size),
640 },
641 operand: Some(value.operand),
642 },
643 BNInstructionTextTokenType::ArgumentNameToken => {
644 Self::ArgumentName { value: value.value }
645 }
646 BNInstructionTextTokenType::HexDumpByteValueToken => Self::HexDumpByteValue {
647 value: value.value as u8,
648 },
649 BNInstructionTextTokenType::HexDumpSkippedByteToken => Self::HexDumpSkippedByte,
650 BNInstructionTextTokenType::HexDumpInvalidByteToken => Self::HexDumpInvalidByte,
651 BNInstructionTextTokenType::HexDumpTextToken => {
652 Self::HexDumpText { width: value.value }
653 }
654 BNInstructionTextTokenType::OpcodeToken => Self::Opcode,
655 BNInstructionTextTokenType::StringToken => match value.context {
656 BNInstructionTextTokenContext::StringReferenceTokenContext
657 | BNInstructionTextTokenContext::StringDisplayTokenContext => {
658 match value.value {
659 0 => Self::StringContent {
660 ty: StringType::AsciiString,
661 },
662 1 => Self::StringContent {
663 ty: StringType::Utf8String,
664 },
665 2 => Self::StringContent {
666 ty: StringType::Utf16String,
667 },
668 3 => Self::StringContent {
669 ty: StringType::Utf32String,
670 },
671 value => Self::String { value },
675 }
676 }
677 _ => Self::String { value: value.value },
678 },
679 BNInstructionTextTokenType::CharacterConstantToken => Self::CharacterConstant {
680 operand: Some(value.operand),
681 },
682 BNInstructionTextTokenType::KeywordToken => Self::Keyword { value: value.value },
683 BNInstructionTextTokenType::TypeNameToken => Self::TypeName,
684 BNInstructionTextTokenType::FieldNameToken => Self::FieldName {
685 offset: value.value,
686 type_names: {
687 let raw_names =
689 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
690 raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
691 },
692 },
693 BNInstructionTextTokenType::NameSpaceToken => Self::NameSpace,
694 BNInstructionTextTokenType::NameSpaceSeparatorToken => Self::NameSpaceSeparator,
695 BNInstructionTextTokenType::TagToken => Self::Tag,
696 BNInstructionTextTokenType::StructOffsetToken => Self::StructOffset {
697 offset: value.value,
698 type_names: {
699 let raw_names =
701 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
702 raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
703 },
704 },
705 BNInstructionTextTokenType::StructOffsetByteValueToken => Self::StructOffsetByteValue,
706 BNInstructionTextTokenType::StructureHexDumpTextToken => {
707 Self::StructureHexDumpText { width: value.value }
708 }
709 BNInstructionTextTokenType::GotoLabelToken => Self::GotoLabel {
710 target: value.value,
711 },
712 BNInstructionTextTokenType::CommentToken => Self::Comment {
713 target: value.value,
714 },
715 BNInstructionTextTokenType::PossibleValueToken => {
716 Self::PossibleValue { value: value.value }
717 }
718 BNInstructionTextTokenType::PossibleValueTypeToken => Self::PossibleValueType,
720 BNInstructionTextTokenType::ArrayIndexToken => Self::ArrayIndex { index: value.value },
721 BNInstructionTextTokenType::IndentationToken => Self::Indentation,
722 BNInstructionTextTokenType::UnknownMemoryToken => Self::UnknownMemory,
723 BNInstructionTextTokenType::EnumerationMemberToken => Self::EnumerationMember {
724 value: value.value,
725 type_id: {
726 let raw_names =
729 unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
730 raw_names.iter().filter_map(|&r| raw_to_string(r)).next()
731 },
732 },
733 BNInstructionTextTokenType::OperationToken => Self::Operation,
734 BNInstructionTextTokenType::BaseStructureNameToken => Self::BaseStructureName,
735 BNInstructionTextTokenType::BaseStructureSeparatorToken => Self::BaseStructureSeparator,
736 BNInstructionTextTokenType::BraceToken => Self::Brace {
737 hash: match value.value {
738 0 => None,
739 hash => Some(hash),
740 },
741 },
742 BNInstructionTextTokenType::ValueLocationToken => Self::ValueLocation,
743 BNInstructionTextTokenType::CodeSymbolToken => Self::CodeSymbol {
744 value: value.value,
745 size: value.size,
746 },
747 BNInstructionTextTokenType::DataSymbolToken => Self::DataSymbol {
748 value: value.value,
749 size: value.size,
750 },
751 BNInstructionTextTokenType::LocalVariableToken => Self::LocalVariable {
752 variable_id: value.value,
753 ssa_version: value.operand,
754 },
755 BNInstructionTextTokenType::ImportToken => Self::Import {
756 target: value.value,
757 },
758 BNInstructionTextTokenType::AddressDisplayToken => Self::AddressDisplay {
759 address: value.value,
760 },
761 BNInstructionTextTokenType::IndirectImportToken => Self::IndirectImport {
762 target: value.value,
763 size: value.size,
764 source_operand: value.operand,
765 },
766 BNInstructionTextTokenType::ExternalSymbolToken => {
767 Self::ExternalSymbol { value: value.value }
768 }
769 BNInstructionTextTokenType::StackVariableToken => Self::StackVariable {
770 variable_id: value.value,
771 },
772 BNInstructionTextTokenType::AddressSeparatorToken => Self::AddressSeparator,
773 BNInstructionTextTokenType::CollapsedInformationToken => Self::CollapsedInformation,
774 BNInstructionTextTokenType::CollapseStateIndicatorToken => {
775 Self::CollapseStateIndicator {
776 hash: match value.value {
777 0 => None,
778 hash => Some(hash),
779 },
780 }
781 }
782 BNInstructionTextTokenType::NewLineToken => Self::NewLine { value: value.value },
783 }
784 }
785
786 fn try_value(&self) -> Option<u64> {
788 match self {
790 InstructionTextTokenKind::Integer { value, .. } => Some(*value),
791 InstructionTextTokenKind::PossibleAddress { value, .. } => Some(*value),
792 InstructionTextTokenKind::PossibleValue { value, .. } => Some(*value),
793 InstructionTextTokenKind::FloatingPoint { value, .. } => Some(*value as u64),
794 InstructionTextTokenKind::CodeRelativeAddress { value, .. } => Some(*value),
795 InstructionTextTokenKind::ArgumentName { value, .. } => Some(*value),
796 InstructionTextTokenKind::HexDumpByteValue { value, .. } => Some(*value as u64),
797 InstructionTextTokenKind::HexDumpText { width, .. } => Some(*width),
798 InstructionTextTokenKind::String { value, .. } => Some(*value),
799 InstructionTextTokenKind::StringContent { ty, .. } => Some(*ty as u64),
800 InstructionTextTokenKind::Keyword { value, .. } => Some(*value),
801 InstructionTextTokenKind::FieldName { offset, .. } => Some(*offset),
802 InstructionTextTokenKind::StructOffset { offset, .. } => Some(*offset),
803 InstructionTextTokenKind::StructureHexDumpText { width, .. } => Some(*width),
804 InstructionTextTokenKind::GotoLabel { target, .. } => Some(*target),
805 InstructionTextTokenKind::Comment { target, .. } => Some(*target),
806 InstructionTextTokenKind::ArrayIndex { index, .. } => Some(*index),
807 InstructionTextTokenKind::EnumerationMember { value, .. } => Some(*value),
808 InstructionTextTokenKind::LocalVariable { variable_id, .. } => Some(*variable_id),
809 InstructionTextTokenKind::Import { target, .. } => Some(*target),
810 InstructionTextTokenKind::AddressDisplay { address, .. } => Some(*address),
811 InstructionTextTokenKind::IndirectImport { target, .. } => Some(*target),
812 InstructionTextTokenKind::Brace { hash, .. } => *hash,
813 InstructionTextTokenKind::CodeSymbol { value, .. } => Some(*value),
814 InstructionTextTokenKind::DataSymbol { value, .. } => Some(*value),
815 InstructionTextTokenKind::ExternalSymbol { value, .. } => Some(*value),
816 InstructionTextTokenKind::StackVariable { variable_id, .. } => Some(*variable_id),
817 InstructionTextTokenKind::CollapseStateIndicator { hash, .. } => *hash,
818 InstructionTextTokenKind::NewLine { value, .. } => Some(*value),
819 _ => None,
820 }
821 }
822
823 fn try_size(&self) -> Option<usize> {
825 match self {
826 InstructionTextTokenKind::Integer { size, .. } => *size,
827 InstructionTextTokenKind::FloatingPoint { size, .. } => *size,
828 InstructionTextTokenKind::PossibleAddress { size, .. } => *size,
829 InstructionTextTokenKind::CodeRelativeAddress { size, .. } => *size,
830 InstructionTextTokenKind::CodeSymbol { size, .. } => Some(*size),
831 InstructionTextTokenKind::DataSymbol { size, .. } => Some(*size),
832 InstructionTextTokenKind::IndirectImport { size, .. } => Some(*size),
833 _ => None,
834 }
835 }
836
837 fn try_operand(&self) -> Option<usize> {
839 match self {
840 InstructionTextTokenKind::Integer { operand, .. } => *operand,
841 InstructionTextTokenKind::PossibleAddress { operand, .. } => *operand,
842 InstructionTextTokenKind::CodeRelativeAddress { operand, .. } => *operand,
843 InstructionTextTokenKind::CharacterConstant { operand, .. } => *operand,
844 InstructionTextTokenKind::LocalVariable { ssa_version, .. } => Some(*ssa_version),
845 InstructionTextTokenKind::IndirectImport { source_operand, .. } => {
846 Some(*source_operand)
847 }
848 _ => None,
849 }
850 }
851
852 fn try_type_names(&self) -> Option<Vec<String>> {
854 match self {
855 InstructionTextTokenKind::FieldName { type_names, .. } => Some(type_names.clone()),
856 InstructionTextTokenKind::StructOffset { type_names, .. } => Some(type_names.clone()),
857 InstructionTextTokenKind::EnumerationMember { type_id, .. } => {
858 Some(vec![type_id.clone()?])
859 }
860 _ => None,
861 }
862 }
863}
864
865impl From<InstructionTextTokenKind> for BNInstructionTextTokenType {
866 fn from(value: InstructionTextTokenKind) -> Self {
867 match value {
868 InstructionTextTokenKind::Text => BNInstructionTextTokenType::TextToken,
869 InstructionTextTokenKind::Instruction => BNInstructionTextTokenType::InstructionToken,
870 InstructionTextTokenKind::OperandSeparator => {
871 BNInstructionTextTokenType::OperandSeparatorToken
872 }
873 InstructionTextTokenKind::Register => BNInstructionTextTokenType::RegisterToken,
874 InstructionTextTokenKind::Integer { .. } => BNInstructionTextTokenType::IntegerToken,
875 InstructionTextTokenKind::PossibleAddress { .. } => {
876 BNInstructionTextTokenType::PossibleAddressToken
877 }
878 InstructionTextTokenKind::BeginMemoryOperand => {
879 BNInstructionTextTokenType::BeginMemoryOperandToken
880 }
881 InstructionTextTokenKind::EndMemoryOperand => {
882 BNInstructionTextTokenType::EndMemoryOperandToken
883 }
884 InstructionTextTokenKind::FloatingPoint { .. } => {
885 BNInstructionTextTokenType::FloatingPointToken
886 }
887 InstructionTextTokenKind::Annotation => BNInstructionTextTokenType::AnnotationToken,
888 InstructionTextTokenKind::CodeRelativeAddress { .. } => {
889 BNInstructionTextTokenType::CodeRelativeAddressToken
890 }
891 InstructionTextTokenKind::ArgumentName { .. } => {
892 BNInstructionTextTokenType::ArgumentNameToken
893 }
894 InstructionTextTokenKind::HexDumpByteValue { .. } => {
895 BNInstructionTextTokenType::HexDumpByteValueToken
896 }
897 InstructionTextTokenKind::HexDumpSkippedByte => {
898 BNInstructionTextTokenType::HexDumpSkippedByteToken
899 }
900 InstructionTextTokenKind::HexDumpInvalidByte => {
901 BNInstructionTextTokenType::HexDumpInvalidByteToken
902 }
903 InstructionTextTokenKind::HexDumpText { .. } => {
904 BNInstructionTextTokenType::HexDumpTextToken
905 }
906 InstructionTextTokenKind::Opcode => BNInstructionTextTokenType::OpcodeToken,
907 InstructionTextTokenKind::String { .. } => BNInstructionTextTokenType::StringToken,
908 InstructionTextTokenKind::StringContent { .. } => {
909 BNInstructionTextTokenType::StringToken
910 }
911 InstructionTextTokenKind::CharacterConstant { .. } => {
912 BNInstructionTextTokenType::CharacterConstantToken
913 }
914 InstructionTextTokenKind::Keyword { .. } => BNInstructionTextTokenType::KeywordToken,
915 InstructionTextTokenKind::TypeName => BNInstructionTextTokenType::TypeNameToken,
916 InstructionTextTokenKind::FieldName { .. } => {
917 BNInstructionTextTokenType::FieldNameToken
918 }
919 InstructionTextTokenKind::NameSpace => BNInstructionTextTokenType::NameSpaceToken,
920 InstructionTextTokenKind::NameSpaceSeparator => {
921 BNInstructionTextTokenType::NameSpaceSeparatorToken
922 }
923 InstructionTextTokenKind::Tag => BNInstructionTextTokenType::TagToken,
924 InstructionTextTokenKind::StructOffset { .. } => {
925 BNInstructionTextTokenType::StructOffsetToken
926 }
927 InstructionTextTokenKind::StructOffsetByteValue => {
928 BNInstructionTextTokenType::StructOffsetByteValueToken
929 }
930 InstructionTextTokenKind::StructureHexDumpText { .. } => {
931 BNInstructionTextTokenType::StructureHexDumpTextToken
932 }
933 InstructionTextTokenKind::GotoLabel { .. } => {
934 BNInstructionTextTokenType::GotoLabelToken
935 }
936 InstructionTextTokenKind::Comment { .. } => BNInstructionTextTokenType::CommentToken,
937 InstructionTextTokenKind::PossibleValue { .. } => {
938 BNInstructionTextTokenType::PossibleValueToken
939 }
940 InstructionTextTokenKind::PossibleValueType => {
941 BNInstructionTextTokenType::PossibleValueTypeToken
942 }
943 InstructionTextTokenKind::ArrayIndex { .. } => {
944 BNInstructionTextTokenType::ArrayIndexToken
945 }
946 InstructionTextTokenKind::Indentation => BNInstructionTextTokenType::IndentationToken,
947 InstructionTextTokenKind::UnknownMemory => {
948 BNInstructionTextTokenType::UnknownMemoryToken
949 }
950 InstructionTextTokenKind::EnumerationMember { .. } => {
951 BNInstructionTextTokenType::EnumerationMemberToken
952 }
953 InstructionTextTokenKind::Operation => BNInstructionTextTokenType::OperationToken,
954 InstructionTextTokenKind::BaseStructureName => {
955 BNInstructionTextTokenType::BaseStructureNameToken
956 }
957 InstructionTextTokenKind::BaseStructureSeparator => {
958 BNInstructionTextTokenType::BaseStructureSeparatorToken
959 }
960 InstructionTextTokenKind::Brace { .. } => BNInstructionTextTokenType::BraceToken,
961 InstructionTextTokenKind::ValueLocation => {
962 BNInstructionTextTokenType::ValueLocationToken
963 }
964 InstructionTextTokenKind::CodeSymbol { .. } => {
965 BNInstructionTextTokenType::CodeSymbolToken
966 }
967 InstructionTextTokenKind::DataSymbol { .. } => {
968 BNInstructionTextTokenType::DataSymbolToken
969 }
970 InstructionTextTokenKind::LocalVariable { .. } => {
971 BNInstructionTextTokenType::LocalVariableToken
972 }
973 InstructionTextTokenKind::Import { .. } => BNInstructionTextTokenType::ImportToken,
974 InstructionTextTokenKind::AddressDisplay { .. } => {
975 BNInstructionTextTokenType::AddressDisplayToken
976 }
977 InstructionTextTokenKind::IndirectImport { .. } => {
978 BNInstructionTextTokenType::IndirectImportToken
979 }
980 InstructionTextTokenKind::ExternalSymbol { .. } => {
981 BNInstructionTextTokenType::ExternalSymbolToken
982 }
983 InstructionTextTokenKind::StackVariable { .. } => {
984 BNInstructionTextTokenType::StackVariableToken
985 }
986 InstructionTextTokenKind::AddressSeparator => {
987 BNInstructionTextTokenType::AddressSeparatorToken
988 }
989 InstructionTextTokenKind::CollapsedInformation => {
990 BNInstructionTextTokenType::CollapsedInformationToken
991 }
992 InstructionTextTokenKind::CollapseStateIndicator { .. } => {
993 BNInstructionTextTokenType::CollapseStateIndicatorToken
994 }
995 InstructionTextTokenKind::NewLine { .. } => BNInstructionTextTokenType::NewLineToken,
996 }
997 }
998}
999
1000impl Eq for InstructionTextTokenKind {}
1001
1002#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1003pub enum InstructionTextTokenContext {
1004 Normal,
1005 LocalVariable,
1006 DataVariable,
1007 FunctionReturn,
1008 InstructionAddress,
1009 ILInstructionIndex,
1010 ConstData,
1011 ConstStringData,
1013 StringReference,
1015 StringDataVariable,
1017 StringDisplay,
1021 Collapsed,
1023 Expanded,
1025 CollapsiblePadding,
1027 DerivedStringReference,
1029}
1030
1031impl From<BNInstructionTextTokenContext> for InstructionTextTokenContext {
1032 fn from(value: BNInstructionTextTokenContext) -> Self {
1033 match value {
1034 BNInstructionTextTokenContext::NoTokenContext => Self::Normal,
1035 BNInstructionTextTokenContext::LocalVariableTokenContext => Self::LocalVariable,
1036 BNInstructionTextTokenContext::DataVariableTokenContext => Self::DataVariable,
1037 BNInstructionTextTokenContext::FunctionReturnTokenContext => Self::FunctionReturn,
1038 BNInstructionTextTokenContext::InstructionAddressTokenContext => {
1039 Self::InstructionAddress
1040 }
1041 BNInstructionTextTokenContext::ILInstructionIndexTokenContext => {
1042 Self::ILInstructionIndex
1043 }
1044 BNInstructionTextTokenContext::ConstDataTokenContext => Self::ConstData,
1045 BNInstructionTextTokenContext::ConstStringDataTokenContext => Self::ConstStringData,
1047 BNInstructionTextTokenContext::StringReferenceTokenContext => Self::StringReference,
1048 BNInstructionTextTokenContext::StringDataVariableTokenContext => {
1049 Self::StringDataVariable
1050 }
1051 BNInstructionTextTokenContext::StringDisplayTokenContext => Self::StringDisplay,
1052 BNInstructionTextTokenContext::ContentCollapsedContext => Self::Collapsed,
1054 BNInstructionTextTokenContext::ContentExpandedContext => Self::Expanded,
1055 BNInstructionTextTokenContext::ContentCollapsiblePadding => Self::CollapsiblePadding,
1056 BNInstructionTextTokenContext::DerivedStringReferenceTokenContext => {
1057 Self::DerivedStringReference
1058 }
1059 }
1060 }
1061}
1062
1063impl From<InstructionTextTokenContext> for BNInstructionTextTokenContext {
1064 fn from(value: InstructionTextTokenContext) -> Self {
1065 match value {
1066 InstructionTextTokenContext::Normal => Self::NoTokenContext,
1067 InstructionTextTokenContext::LocalVariable => Self::LocalVariableTokenContext,
1068 InstructionTextTokenContext::DataVariable => Self::DataVariableTokenContext,
1069 InstructionTextTokenContext::FunctionReturn => Self::FunctionReturnTokenContext,
1070 InstructionTextTokenContext::InstructionAddress => Self::InstructionAddressTokenContext,
1071 InstructionTextTokenContext::ILInstructionIndex => Self::ILInstructionIndexTokenContext,
1072 InstructionTextTokenContext::ConstData => Self::ConstDataTokenContext,
1073 InstructionTextTokenContext::ConstStringData => Self::ConstStringDataTokenContext,
1074 InstructionTextTokenContext::StringReference => Self::StringReferenceTokenContext,
1075 InstructionTextTokenContext::StringDataVariable => Self::StringDataVariableTokenContext,
1076 InstructionTextTokenContext::StringDisplay => Self::StringDisplayTokenContext,
1077 InstructionTextTokenContext::Collapsed => Self::ContentCollapsedContext,
1078 InstructionTextTokenContext::Expanded => Self::ContentExpandedContext,
1079 InstructionTextTokenContext::CollapsiblePadding => Self::ContentCollapsiblePadding,
1080 InstructionTextTokenContext::DerivedStringReference => {
1081 Self::DerivedStringReferenceTokenContext
1082 }
1083 }
1084 }
1085}
1086
1087#[repr(transparent)]
1088pub struct DisassemblyTextRenderer {
1089 handle: NonNull<BNDisassemblyTextRenderer>,
1090}
1091
1092impl DisassemblyTextRenderer {
1093 pub unsafe fn ref_from_raw(handle: NonNull<BNDisassemblyTextRenderer>) -> Ref<Self> {
1094 Ref::new(Self { handle })
1095 }
1096
1097 pub fn from_function(func: &Function, settings: Option<&DisassemblySettings>) -> Ref<Self> {
1098 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1099 let result = unsafe { BNCreateDisassemblyTextRenderer(func.handle, settings_ptr) };
1100 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1101 }
1102
1103 pub fn from_llil<M: FunctionMutability, F: FunctionForm>(
1104 func: &LowLevelILFunction<M, F>,
1105 settings: Option<&DisassemblySettings>,
1106 ) -> Ref<Self> {
1107 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1108 let result =
1109 unsafe { BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1110 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1111 }
1112
1113 pub fn from_mlil(
1114 func: &MediumLevelILFunction,
1115 settings: Option<&DisassemblySettings>,
1116 ) -> Ref<Self> {
1117 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1118 let result =
1119 unsafe { BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1120 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1121 }
1122
1123 pub fn from_hlil(
1124 func: &HighLevelILFunction,
1125 settings: Option<&DisassemblySettings>,
1126 ) -> Ref<Self> {
1127 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1128 let result =
1129 unsafe { BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1130 unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) }
1131 }
1132
1133 pub fn function(&self) -> Ref<Function> {
1134 let result = unsafe { BNGetDisassemblyTextRendererFunction(self.handle.as_ptr()) };
1135 assert!(!result.is_null());
1136 unsafe { Function::ref_from_raw(result) }
1137 }
1138
1139 pub fn llil<M: FunctionMutability, F: FunctionForm>(&self) -> Ref<LowLevelILFunction<M, F>> {
1140 let result =
1141 unsafe { BNGetDisassemblyTextRendererLowLevelILFunction(self.handle.as_ptr()) };
1142 assert!(!result.is_null());
1143 unsafe { LowLevelILFunction::ref_from_raw(result) }
1144 }
1145
1146 pub fn mlil(&self) -> Ref<MediumLevelILFunction> {
1147 let result =
1148 unsafe { BNGetDisassemblyTextRendererMediumLevelILFunction(self.handle.as_ptr()) };
1149 assert!(!result.is_null());
1150 unsafe { MediumLevelILFunction::ref_from_raw(result) }
1151 }
1152
1153 pub fn hlil(&self) -> Ref<HighLevelILFunction> {
1154 let result =
1155 unsafe { BNGetDisassemblyTextRendererHighLevelILFunction(self.handle.as_ptr()) };
1156 assert!(!result.is_null());
1157 unsafe { HighLevelILFunction::ref_from_raw(result, true) }
1158 }
1159
1160 pub fn basic_block(&self) -> Option<Ref<BasicBlock<NativeBlock>>> {
1161 let result = unsafe { BNGetDisassemblyTextRendererBasicBlock(self.handle.as_ptr()) };
1162 if result.is_null() {
1163 return None;
1164 }
1165 Some(unsafe { Ref::new(BasicBlock::from_raw(result, NativeBlock::new())) })
1166 }
1167
1168 pub fn set_basic_block(&self, value: Option<&BasicBlock<NativeBlock>>) {
1169 let block_ptr = value.map(|b| b.handle).unwrap_or(ptr::null_mut());
1170 unsafe { BNSetDisassemblyTextRendererBasicBlock(self.handle.as_ptr(), block_ptr) }
1171 }
1172
1173 pub fn arch(&self) -> CoreArchitecture {
1174 let result = unsafe { BNGetDisassemblyTextRendererArchitecture(self.handle.as_ptr()) };
1175 assert!(!result.is_null());
1176 unsafe { CoreArchitecture::from_raw(result) }
1177 }
1178
1179 pub fn set_arch(&self, value: CoreArchitecture) {
1180 unsafe { BNSetDisassemblyTextRendererArchitecture(self.handle.as_ptr(), value.handle) }
1181 }
1182
1183 pub fn settings(&self) -> Ref<DisassemblySettings> {
1184 let result = unsafe { BNGetDisassemblyTextRendererSettings(self.handle.as_ptr()) };
1185 unsafe { DisassemblySettings::ref_from_raw(result) }
1186 }
1187
1188 pub fn set_settings(&self, settings: Option<&DisassemblySettings>) {
1189 let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1190 unsafe { BNSetDisassemblyTextRendererSettings(self.handle.as_ptr(), settings_ptr) }
1191 }
1192
1193 pub fn is_il(&self) -> bool {
1194 unsafe { BNIsILDisassemblyTextRenderer(self.handle.as_ptr()) }
1195 }
1196
1197 pub fn has_data_flow(&self) -> bool {
1198 unsafe { BNDisassemblyTextRendererHasDataFlow(self.handle.as_ptr()) }
1199 }
1200
1201 pub fn instruction_annotations(&self, addr: u64) -> Array<InstructionTextToken> {
1203 let mut count = 0;
1204 let result = unsafe {
1205 BNGetDisassemblyTextRendererInstructionAnnotations(
1206 self.handle.as_ptr(),
1207 addr,
1208 &mut count,
1209 )
1210 };
1211 assert!(!result.is_null());
1212 unsafe { Array::new(result, count, ()) }
1213 }
1214
1215 pub fn instruction_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1217 let mut count = 0;
1218 let mut length = 0;
1219 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1220 let result = unsafe {
1221 BNGetDisassemblyTextRendererInstructionText(
1222 self.handle.as_ptr(),
1223 addr,
1224 &mut length,
1225 &mut lines,
1226 &mut count,
1227 )
1228 };
1229 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1230 }
1231
1232 pub fn disassembly_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1234 let mut count = 0;
1235 let mut length = 0;
1236 let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1237 let result = unsafe {
1238 BNGetDisassemblyTextRendererLines(
1239 self.handle.as_ptr(),
1240 addr,
1241 &mut length,
1242 &mut lines,
1243 &mut count,
1244 )
1245 };
1246 result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1247 }
1248
1249 pub fn is_integer_token(token_type: InstructionTextTokenType) -> bool {
1252 unsafe { BNIsIntegerToken(token_type) }
1253 }
1254
1255 pub fn reset_deduplicated_comments(&self) {
1256 unsafe { BNResetDisassemblyTextRendererDeduplicatedComments(self.handle.as_ptr()) }
1257 }
1258
1259 pub fn symbol_tokens(
1260 &self,
1261 addr: u64,
1262 size: usize,
1263 operand: Option<usize>,
1264 ) -> Option<Array<InstructionTextToken>> {
1265 let operand = operand.unwrap_or(0xffffffff);
1266 let mut count = 0;
1267 let mut tokens: *mut BNInstructionTextToken = ptr::null_mut();
1268 let result = unsafe {
1269 BNGetDisassemblyTextRendererSymbolTokens(
1270 self.handle.as_ptr(),
1271 addr,
1272 size,
1273 operand,
1274 &mut tokens,
1275 &mut count,
1276 )
1277 };
1278 result.then(|| unsafe { Array::new(tokens, count, ()) })
1279 }
1280
1281 pub fn stack_var_reference_tokens(
1282 &self,
1283 stack_ref: StackVariableReference,
1284 ) -> Array<InstructionTextToken> {
1285 let mut stack_ref_raw = StackVariableReference::into_raw(stack_ref);
1286 let mut count = 0;
1287 let tokens = unsafe {
1288 BNGetDisassemblyTextRendererStackVariableReferenceTokens(
1289 self.handle.as_ptr(),
1290 &mut stack_ref_raw,
1291 &mut count,
1292 )
1293 };
1294 StackVariableReference::free_raw(stack_ref_raw);
1295 assert!(!tokens.is_null());
1296 unsafe { Array::new(tokens, count, ()) }
1297 }
1298
1299 pub fn integer_token(
1300 &self,
1301 int_token: InstructionTextToken,
1302 location: impl Into<Location>,
1303 ) -> Array<InstructionTextToken> {
1304 let location = location.into();
1305 let arch = location
1306 .arch
1307 .map(|a| a.handle)
1308 .unwrap_or_else(std::ptr::null_mut);
1309 let mut count = 0;
1310 let mut int_token_raw = InstructionTextToken::into_raw(int_token);
1311 let tokens = unsafe {
1312 BNGetDisassemblyTextRendererIntegerTokens(
1313 self.handle.as_ptr(),
1314 &mut int_token_raw,
1315 arch,
1316 location.addr,
1317 &mut count,
1318 )
1319 };
1320 InstructionTextToken::free_raw(int_token_raw);
1321 assert!(!tokens.is_null());
1322 unsafe { Array::new(tokens, count, ()) }
1323 }
1324
1325 pub fn wrap_comment(
1326 &self,
1327 cur_line: DisassemblyTextLine,
1328 comment: &str,
1329 has_auto_annotations: bool,
1330 leading_spaces: &str,
1331 indent_spaces: &str,
1332 ) -> Array<DisassemblyTextLine> {
1333 let cur_line_raw = DisassemblyTextLine::into_raw(cur_line);
1334 let comment_raw = comment.to_cstr();
1335 let leading_spaces_raw = leading_spaces.to_cstr();
1336 let indent_spaces_raw = indent_spaces.to_cstr();
1337 let mut count = 0;
1338 let lines = unsafe {
1339 BNDisassemblyTextRendererWrapComment(
1340 self.handle.as_ptr(),
1341 &cur_line_raw,
1342 &mut count,
1343 comment_raw.as_ref().as_ptr() as *const ffi::c_char,
1344 has_auto_annotations,
1345 leading_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1346 indent_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1347 )
1348 };
1349 DisassemblyTextLine::free_raw(cur_line_raw);
1350 assert!(!lines.is_null());
1351 unsafe { Array::new(lines, count, ()) }
1352 }
1353}
1354
1355impl ToOwned for DisassemblyTextRenderer {
1356 type Owned = Ref<Self>;
1357
1358 fn to_owned(&self) -> Self::Owned {
1359 unsafe { RefCountable::inc_ref(self) }
1360 }
1361}
1362
1363unsafe impl RefCountable for DisassemblyTextRenderer {
1364 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1365 Ref::new(Self {
1366 handle: NonNull::new(BNNewDisassemblyTextRendererReference(
1367 handle.handle.as_ptr(),
1368 ))
1369 .unwrap(),
1370 })
1371 }
1372
1373 unsafe fn dec_ref(handle: &Self) {
1374 BNFreeDisassemblyTextRenderer(handle.handle.as_ptr());
1375 }
1376}
1377
1378#[derive(PartialEq, Eq, Hash)]
1380pub struct DisassemblySettings {
1381 pub(crate) handle: *mut BNDisassemblySettings,
1382}
1383
1384impl DisassemblySettings {
1385 pub fn ref_from_raw(handle: *mut BNDisassemblySettings) -> Ref<Self> {
1386 debug_assert!(!handle.is_null());
1387 unsafe { Ref::new(Self { handle }) }
1388 }
1389
1390 pub fn new() -> Ref<Self> {
1391 let handle = unsafe { BNCreateDisassemblySettings() };
1392 Self::ref_from_raw(handle)
1393 }
1394
1395 pub fn set_option(&self, option: DisassemblyOption, state: bool) {
1396 unsafe { BNSetDisassemblySettingsOption(self.handle, option, state) }
1397 }
1398
1399 pub fn is_option_set(&self, option: DisassemblyOption) -> bool {
1400 unsafe { BNIsDisassemblySettingsOptionSet(self.handle, option) }
1401 }
1402}
1403
1404impl ToOwned for DisassemblySettings {
1405 type Owned = Ref<Self>;
1406
1407 fn to_owned(&self) -> Self::Owned {
1408 unsafe { RefCountable::inc_ref(self) }
1409 }
1410}
1411
1412unsafe impl RefCountable for DisassemblySettings {
1413 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1414 Ref::new(Self {
1415 handle: BNNewDisassemblySettingsReference(handle.handle),
1416 })
1417 }
1418
1419 unsafe fn dec_ref(handle: &Self) {
1420 BNFreeDisassemblySettings(handle.handle);
1421 }
1422}