summaryrefslogtreecommitdiff
path: root/rust/src/disassembly.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/disassembly.rs')
-rw-r--r--rust/src/disassembly.rs1208
1 files changed, 847 insertions, 361 deletions
diff --git a/rust/src/disassembly.rs b/rust/src/disassembly.rs
index 5d3da31e..99938e5f 100644
--- a/rust/src/disassembly.rs
+++ b/rust/src/disassembly.rs
@@ -11,467 +11,955 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-
-// TODO : Combine this with the architecture implementation
+#![allow(unused)]
use binaryninjacore_sys::*;
-use crate::string::BnString;
-use crate::{BN_FULL_CONFIDENCE, BN_INVALID_EXPR};
+use crate::string::{raw_to_string, strings_to_string_list, BnString};
use crate::rc::*;
+use crate::confidence::MAX_CONFIDENCE;
+use crate::function::HighlightColor;
+use crate::tags::Tag;
+use crate::types::Type;
use std::convert::From;
-use std::ffi::CStr;
-use std::mem;
-use std::ptr;
+use std::fmt::{Display, Formatter};
+pub type DisassemblyOption = BNDisassemblyOption;
pub type InstructionTextTokenType = BNInstructionTextTokenType;
-pub type InstructionTextTokenContext = BNInstructionTextTokenContext;
-
-// InstructionTextTokenType's; * = Implemented
-// *TextToken = 0,
-// *InstructionToken = 1,
-// *OperandSeparatorToken = 2,
-// *RegisterToken = 3,
-// *IntegerToken = 4,
-// *PossibleAddressToken = 5,
-// *BeginMemoryOperandToken = 6,
-// *EndMemoryOperandToken = 7,
-// *FloatingPointToken = 8,
-// AnnotationToken = 9,
-// *CodeRelativeAddressToken = 10,
-// ArgumentNameToken = 11,
-// HexDumpByteValueToken = 12,
-// HexDumpSkippedByteToken = 13,
-// HexDumpInvalidByteToken = 14,
-// HexDumpTextToken = 15,
-// OpcodeToken = 16,
-// *StringToken = 17,
-// CharacterConstantToken = 18,
-// *KeywordToken = 19,
-// *TypeNameToken = 20,
-// *FieldNameToken = 21,
-// *NameSpaceToken = 22,
-// NameSpaceSeparatorToken = 23,
-// TagToken = 24,
-// StructOffsetToken = 25,
-// StructOffsetByteValueToken = 26,
-// StructureHexDumpTextToken = 27,
-// *GotoLabelToken = 28,
-// CommentToken = 29,
-// PossibleValueToken = 30,
-// PossibleValueTypeToken = 31,
-// ArrayIndexToken = 32,
-// *IndentationToken = 33,
-// UnknownMemoryToken = 34,
-// CodeSymbolToken = 64,
-// DataSymbolToken = 65,
-// LocalVariableToken = 66,
-// ImportToken = 67,
-// AddressDisplayToken = 68,
-// IndirectImportToken = 69,
-// ExternalSymbolToken = 70,
-
-#[repr(transparent)]
-pub struct InstructionTextToken(pub(crate) BNInstructionTextToken);
+pub type StringType = BNStringType;
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum InstructionTextTokenContents {
- Text,
- Instruction,
- OperandSeparator,
- Register,
- Integer(u64), // TODO size?
- PossibleAddress(u64), // TODO size?
- BeginMemoryOperand,
- EndMemoryOperand,
- FloatingPoint,
- CodeRelativeAddress(u64),
- String(u64),
- Keyword,
- TypeName,
- FieldName,
- NameSpace,
- GotoLabel(u64),
- Indentation,
- Brace,
+#[derive(Clone, PartialEq, Debug, Default)]
+pub struct DisassemblyTextLine {
+ pub address: u64,
+ pub instruction_index: usize,
+ pub tokens: Vec<InstructionTextToken>,
+ pub highlight: HighlightColor,
+ pub tags: Vec<Ref<Tag>>,
+ pub type_info: DisassemblyTextLineTypeInfo,
}
-impl InstructionTextToken {
- pub(crate) unsafe fn from_raw(raw: &BNInstructionTextToken) -> &Self {
- mem::transmute(raw)
+impl DisassemblyTextLine {
+ pub(crate) fn from_raw(value: &BNDisassemblyTextLine) -> Self {
+ let raw_tokens = unsafe { std::slice::from_raw_parts(value.tokens, value.count) };
+ let tokens: Vec<_> = raw_tokens
+ .iter()
+ .map(InstructionTextToken::from_raw)
+ .collect();
+ // SAFETY: Increment the tag ref as we are going from ref to owned.
+ let raw_tags = unsafe { std::slice::from_raw_parts(value.tags, value.tagCount) };
+ let tags: Vec<_> = raw_tags
+ .iter()
+ .map(|&t| unsafe { Tag::from_raw(t) }.to_owned())
+ .collect();
+ Self {
+ address: value.addr,
+ instruction_index: value.instrIndex,
+ tokens,
+ highlight: value.highlight.into(),
+ tags,
+ type_info: DisassemblyTextLineTypeInfo::from_raw(&value.typeInfo),
+ }
}
- pub(crate) fn into_raw(self) -> BNInstructionTextToken {
- mem::ManuallyDrop::new(self).0
+ /// Convert into a raw [BNDisassemblyTextLine], use with caution.
+ ///
+ /// NOTE: The allocations here for tokens and tags MUST be freed by rust using [Self::free_raw].
+ pub(crate) fn into_raw(value: Self) -> BNDisassemblyTextLine {
+ // NOTE: The instruction text and type names fields are being leaked here. To be freed with [Self::free_raw].
+ let tokens: Box<[BNInstructionTextToken]> = value
+ .tokens
+ .into_iter()
+ .map(InstructionTextToken::into_raw)
+ .collect();
+ let tags: Box<[*mut BNTag]> = value
+ .tags
+ .into_iter()
+ .map(|t| {
+ // SAFETY: The tags ref will be temporarily incremented here, until [Self::free_raw] is called.
+ // SAFETY: This is so that tags lifetime is long enough, as we might be the last holders of the ref.
+ unsafe { Ref::into_raw(t) }.handle
+ })
+ .collect();
+ BNDisassemblyTextLine {
+ addr: value.address,
+ instrIndex: value.instruction_index,
+ count: tokens.len(),
+ // NOTE: Leaking tokens here to be freed with [Self::free_raw].
+ tokens: Box::leak(tokens).as_mut_ptr(),
+ highlight: value.highlight.into(),
+ tagCount: tags.len(),
+ // NOTE: Leaking tags here to be freed with [Self::free_raw].
+ tags: Box::leak(tags).as_mut_ptr(),
+ typeInfo: DisassemblyTextLineTypeInfo::into_raw(value.type_info),
+ }
}
- pub fn new(text: &str, contents: InstructionTextTokenContents) -> Self {
- let (value, address) = match contents {
- InstructionTextTokenContents::Integer(v) => (v, 0),
- InstructionTextTokenContents::PossibleAddress(v)
- | InstructionTextTokenContents::CodeRelativeAddress(v)
- | InstructionTextTokenContents::GotoLabel(v) => (v, v),
- InstructionTextTokenContents::String(v) => (v, 0),
- _ => (0, 0),
- };
+ /// Frees raw object created with [Self::into_raw], use with caution.
+ ///
+ /// NOTE: The allocations freed MUST have been created in rust using [Self::into_raw].
+ pub(crate) fn free_raw(value: BNDisassemblyTextLine) {
+ // Free the token list
+ let raw_tokens = unsafe { std::slice::from_raw_parts_mut(value.tokens, value.count) };
+ let boxed_tokens = unsafe { Box::from_raw(raw_tokens) };
+ for token in boxed_tokens {
+ // SAFETY: As we have leaked the token contents we need to now free them (text and typeNames).
+ InstructionTextToken::free_raw(token);
+ }
+ // Free the tag list
+ let raw_tags = unsafe { std::slice::from_raw_parts_mut(value.tags, value.tagCount) };
+ let boxed_tags = unsafe { Box::from_raw(raw_tags) };
+ for tag in boxed_tags {
+ // SAFETY: As we have incremented the tags ref in [Self::into_raw] we must now decrement.
+ let _ = unsafe { Tag::ref_from_raw(tag) };
+ }
+ // Free the type info
+ DisassemblyTextLineTypeInfo::free_raw(value.typeInfo);
+ }
- let type_ = match contents {
- InstructionTextTokenContents::Text => InstructionTextTokenType::TextToken,
- InstructionTextTokenContents::Instruction => InstructionTextTokenType::InstructionToken,
- InstructionTextTokenContents::OperandSeparator => {
- InstructionTextTokenType::OperandSeparatorToken
- }
- InstructionTextTokenContents::Register => InstructionTextTokenType::RegisterToken,
- InstructionTextTokenContents::Integer(_) => InstructionTextTokenType::IntegerToken,
- InstructionTextTokenContents::PossibleAddress(_) => {
- InstructionTextTokenType::PossibleAddressToken
- }
- InstructionTextTokenContents::BeginMemoryOperand => {
- InstructionTextTokenType::BeginMemoryOperandToken
- }
- InstructionTextTokenContents::EndMemoryOperand => {
- InstructionTextTokenType::EndMemoryOperandToken
- }
- InstructionTextTokenContents::FloatingPoint => {
- InstructionTextTokenType::FloatingPointToken
- }
- InstructionTextTokenContents::CodeRelativeAddress(_) => {
- InstructionTextTokenType::CodeRelativeAddressToken
- }
- InstructionTextTokenContents::String(_) => InstructionTextTokenType::StringToken,
- InstructionTextTokenContents::Keyword => InstructionTextTokenType::KeywordToken,
- InstructionTextTokenContents::TypeName => InstructionTextTokenType::TypeNameToken,
- InstructionTextTokenContents::FieldName => InstructionTextTokenType::FieldNameToken,
- InstructionTextTokenContents::NameSpace => InstructionTextTokenType::NameSpaceToken,
- InstructionTextTokenContents::GotoLabel(_) => InstructionTextTokenType::GotoLabelToken,
- InstructionTextTokenContents::Indentation => InstructionTextTokenType::IndentationToken,
- InstructionTextTokenContents::Brace => InstructionTextTokenType::BraceToken,
- };
+ pub fn new(tokens: Vec<InstructionTextToken>) -> Self {
+ Self {
+ tokens,
+ ..Default::default()
+ }
+ }
+}
- let width = text.len() as u64;
+impl From<&str> for DisassemblyTextLine {
+ fn from(value: &str) -> Self {
+ Self::new(vec![InstructionTextToken::new(
+ value,
+ InstructionTextTokenKind::Text,
+ )])
+ }
+}
- InstructionTextToken(BNInstructionTextToken {
- type_,
- text: BnString::new(text).into_raw(),
+impl From<String> for DisassemblyTextLine {
+ fn from(value: String) -> Self {
+ Self::new(vec![InstructionTextToken::new(
value,
- width,
- size: 0,
- operand: 0xffff_ffff,
- context: InstructionTextTokenContext::NoTokenContext,
- confidence: BN_FULL_CONFIDENCE,
- address,
- typeNames: ptr::null_mut(),
- namesCount: 0,
- exprIndex: BN_INVALID_EXPR,
- })
+ InstructionTextTokenKind::Text,
+ )])
}
+}
- pub fn set_value(&mut self, value: u64) {
- self.0.value = value;
+impl Display for DisassemblyTextLine {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ for token in &self.tokens {
+ write!(f, "{}", token)?;
+ }
+ Ok(())
}
+}
- pub fn set_context(&mut self, context: InstructionTextTokenContext) {
- self.0.context = context;
+impl CoreArrayProvider for DisassemblyTextLine {
+ type Raw = BNDisassemblyTextLine;
+ type Context = ();
+ type Wrapped<'a> = Self;
+}
+
+unsafe impl CoreArrayProviderInner for DisassemblyTextLine {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeDisassemblyTextLines(raw, count)
}
- pub fn text(&self) -> &str {
- unsafe { CStr::from_ptr(self.0.text) }.to_str().unwrap()
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::from_raw(raw)
}
+}
- pub fn contents(&self) -> InstructionTextTokenContents {
- use self::BNInstructionTextTokenType::*;
- use self::InstructionTextTokenContents::*;
+#[derive(Default, Clone, PartialEq, Eq, Debug, Hash)]
+pub struct DisassemblyTextLineTypeInfo {
+ pub has_type_info: bool,
+ pub parent_type: Option<Ref<Type>>,
+ pub field_index: usize,
+ pub offset: u64,
+}
- match self.0.type_ {
- TextToken => Text,
- InstructionToken => Instruction,
- OperandSeparatorToken => OperandSeparator,
- RegisterToken => Register,
- IntegerToken => Integer(self.0.value),
- PossibleAddressToken => PossibleAddress(self.0.value),
- BeginMemoryOperandToken => BeginMemoryOperand,
- EndMemoryOperandToken => EndMemoryOperand,
- FloatingPointToken => FloatingPoint,
- CodeRelativeAddressToken => CodeRelativeAddress(self.0.value),
- _ => unimplemented!("woops"),
+impl DisassemblyTextLineTypeInfo {
+ pub(crate) fn from_raw(value: &BNDisassemblyTextLineTypeInfo) -> Self {
+ Self {
+ has_type_info: value.hasTypeInfo,
+ parent_type: match value.parentType.is_null() {
+ false => Some(unsafe { Type::from_raw(value.parentType).to_owned() }),
+ true => None,
+ },
+ field_index: value.fieldIndex,
+ offset: value.offset,
}
}
- pub fn context(&self) -> InstructionTextTokenContext {
- self.0.context
+ pub(crate) fn from_owned_raw(value: BNDisassemblyTextLineTypeInfo) -> Self {
+ Self {
+ has_type_info: value.hasTypeInfo,
+ parent_type: match value.parentType.is_null() {
+ false => Some(unsafe { Type::ref_from_raw(value.parentType) }),
+ true => None,
+ },
+ field_index: value.fieldIndex,
+ offset: value.offset,
+ }
}
- pub fn size(&self) -> usize {
- self.0.size
+ pub(crate) fn into_raw(value: Self) -> BNDisassemblyTextLineTypeInfo {
+ BNDisassemblyTextLineTypeInfo {
+ hasTypeInfo: value.has_type_info,
+ parentType: value
+ .parent_type
+ .map(|t| unsafe { Ref::into_raw(t) }.handle)
+ .unwrap_or(std::ptr::null_mut()),
+ fieldIndex: value.field_index,
+ offset: value.offset,
+ }
}
- pub fn operand(&self) -> usize {
- self.0.operand
+ pub(crate) fn into_owned_raw(value: &Self) -> BNDisassemblyTextLineTypeInfo {
+ BNDisassemblyTextLineTypeInfo {
+ hasTypeInfo: value.has_type_info,
+ parentType: value
+ .parent_type
+ .as_ref()
+ .map(|t| t.handle)
+ .unwrap_or(std::ptr::null_mut()),
+ fieldIndex: value.field_index,
+ offset: value.offset,
+ }
}
- pub fn address(&self) -> u64 {
- self.0.address
+ pub(crate) fn free_raw(value: BNDisassemblyTextLineTypeInfo) {
+ if !value.parentType.is_null() {
+ let _ = unsafe { Type::ref_from_raw(value.parentType) };
+ }
}
+}
- pub fn expr_index(&self) -> usize {
- self.0.exprIndex
- }
+#[derive(Debug, Clone, PartialEq)]
+pub struct InstructionTextToken {
+ pub address: u64,
+ pub text: String,
+ pub confidence: u8,
+ pub context: InstructionTextTokenContext,
+ // TODO: Document that this is not necessary to set and that this is valid in a limited context.
+ pub expr_index: usize,
+ pub kind: InstructionTextTokenKind,
}
-impl Default for InstructionTextToken {
- fn default() -> Self {
- InstructionTextToken(BNInstructionTextToken {
- type_: InstructionTextTokenType::TextToken,
- text: ptr::null_mut(),
- value: 0,
- width: 0,
- size: 0,
- operand: 0,
- context: InstructionTextTokenContext::NoTokenContext,
- confidence: BN_FULL_CONFIDENCE,
- address: 0,
- typeNames: ptr::null_mut(),
- namesCount: 0,
- exprIndex: BN_INVALID_EXPR,
- })
+impl InstructionTextToken {
+ pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
+ Self {
+ address: value.address,
+ text: raw_to_string(value.text).unwrap(),
+ confidence: value.confidence,
+ context: value.context.into(),
+ expr_index: value.exprIndex,
+ kind: InstructionTextTokenKind::from_raw(value),
+ }
}
-}
-impl Clone for InstructionTextToken {
- fn clone(&self) -> Self {
- InstructionTextToken(BNInstructionTextToken {
- type_: self.0.type_,
- context: self.0.context,
- address: self.0.address,
- size: self.0.size,
- operand: self.0.operand,
- value: self.0.value,
+ pub(crate) fn into_raw(value: Self) -> BNInstructionTextToken {
+ let bn_text = BnString::new(value.text);
+ // These can be gathered from value.kind
+ let kind_value = value.kind.try_value().unwrap_or(0);
+ let operand = value.kind.try_operand().unwrap_or(0);
+ let size = value.kind.try_size().unwrap_or(0);
+ let type_names = value.kind.try_type_names().unwrap_or_default();
+ BNInstructionTextToken {
+ type_: value.kind.into(),
+ // NOTE: Expected to be freed with `InstructionTextToken::free_raw`.
+ text: BnString::into_raw(bn_text),
+ value: kind_value,
+ // TODO: Where is this even used?
width: 0,
- text: BnString::new(self.text()).into_raw(),
- confidence: 0xff,
- typeNames: ptr::null_mut(),
- namesCount: 0,
- exprIndex: self.0.exprIndex,
- })
+ size,
+ operand,
+ context: value.context.into(),
+ confidence: value.confidence,
+ address: value.address,
+ // NOTE: Expected to be freed with `InstructionTextToken::free_raw`.
+ typeNames: strings_to_string_list(&type_names),
+ namesCount: type_names.len(),
+ exprIndex: value.expr_index,
+ }
}
-}
-impl Drop for InstructionTextToken {
- fn drop(&mut self) {
- if !self.0.text.is_null() {
- let _owned = unsafe { BnString::from_raw(self.0.text) };
+ pub(crate) fn free_raw(value: BNInstructionTextToken) {
+ if !value.text.is_null() {
+ unsafe { BNFreeString(value.text) };
+ }
+ if !value.typeNames.is_null() {
+ unsafe { BNFreeStringList(value.typeNames, value.namesCount) };
}
- if !self.0.typeNames.is_null() && self.0.namesCount != 0 {
- unsafe { BNFreeStringList(self.0.typeNames, self.0.namesCount) }
+ }
+
+ pub fn new(text: impl Into<String>, kind: InstructionTextTokenKind) -> Self {
+ Self {
+ address: 0,
+ text: text.into(),
+ confidence: MAX_CONFIDENCE,
+ context: InstructionTextTokenContext::Normal,
+ expr_index: 0,
+ kind,
+ }
+ }
+
+ pub fn new_with_address(
+ address: u64,
+ text: impl Into<String>,
+ kind: InstructionTextTokenKind,
+ ) -> Self {
+ Self {
+ address,
+ text: text.into(),
+ confidence: MAX_CONFIDENCE,
+ context: InstructionTextTokenContext::Normal,
+ expr_index: 0,
+ kind,
}
}
}
+impl Display for InstructionTextToken {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.text.fmt(f)
+ }
+}
+
impl CoreArrayProvider for InstructionTextToken {
type Raw = BNInstructionTextToken;
type Context = ();
- type Wrapped<'a> = &'a Self;
+ type Wrapped<'a> = Self;
}
+
unsafe impl CoreArrayProviderInner for InstructionTextToken {
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ // SAFETY: The Array MUST have been allocated on the core side. This will `delete[] raw`.
BNFreeInstructionText(raw, count)
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- core::mem::transmute(raw)
+ Self::from_raw(raw)
}
}
impl CoreArrayProvider for Array<InstructionTextToken> {
type Raw = BNInstructionTextLine;
type Context = ();
- type Wrapped<'a> = mem::ManuallyDrop<Self>;
+ type Wrapped<'a> = std::mem::ManuallyDrop<Self>;
}
+
unsafe impl CoreArrayProviderInner for Array<InstructionTextToken> {
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ // SAFETY: The Array MUST have been allocated on the core side. This will `delete[] raw`.
BNFreeInstructionTextLines(raw, count)
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- mem::ManuallyDrop::new(Self::new(raw.tokens, raw.count, ()))
+ // TODO: This is insane.
+ std::mem::ManuallyDrop::new(Self::new(raw.tokens, raw.count, ()))
}
}
-#[repr(transparent)]
-pub struct DisassemblyTextLine(pub(crate) BNDisassemblyTextLine);
-
-impl DisassemblyTextLine {
- // TODO : this should probably be removed, though it doesn't actually hurt anything
- pub fn debug_print(&self) {
- println!("{}", self);
- }
-
- pub fn addr(&self) -> u64 {
- self.0.addr
- }
-
- pub fn instr_idx(&self) -> usize {
- self.0.instrIndex
- }
+#[derive(Clone, PartialEq, Debug)]
+pub enum InstructionTextTokenKind {
+ Text,
+ Instruction,
+ OperandSeparator,
+ Register,
+ Integer {
+ value: u64,
+ /// Size of the integer
+ size: Option<usize>,
+ },
+ PossibleAddress {
+ value: u64,
+ /// Size of the address
+ size: Option<usize>,
+ },
+ BeginMemoryOperand,
+ EndMemoryOperand,
+ FloatingPoint {
+ value: f64,
+ /// Size of the floating point
+ size: Option<usize>,
+ },
+ Annotation,
+ CodeRelativeAddress {
+ value: u64,
+ size: Option<usize>,
+ },
+ ArgumentName {
+ // TODO: The argument index?
+ value: u64,
+ },
+ HexDumpByteValue {
+ value: u8,
+ },
+ HexDumpSkippedByte,
+ HexDumpInvalidByte,
+ HexDumpText {
+ // TODO: Explain what this does
+ width: u64,
+ },
+ Opcode,
+ String {
+ ty: StringType,
+ },
+ CharacterConstant,
+ Keyword,
+ TypeName,
+ FieldName {
+ /// Offset to this field in the respective structure
+ offset: u64,
+ /// Stores the type names for the referenced field name.
+ ///
+ /// This is typically just the members name.
+ /// For example MyStructure.my_field will have type_names be \["my_field"\].
+ type_names: Vec<String>,
+ },
+ NameSpace,
+ NameSpaceSeparator,
+ Tag,
+ StructOffset {
+ /// Offset to this field in the respective structure
+ offset: u64,
+ // TODO: This makes no sense for struct offset, they dont have types?
+ /// Stores the type names for the referenced field name.
+ type_names: Vec<String>,
+ },
+ // TODO: Unused?
+ StructOffsetByteValue,
+ // TODO: Unused?
+ StructureHexDumpText {
+ // TODO: Explain what this does
+ width: u64,
+ },
+ GotoLabel {
+ target: u64,
+ },
+ Comment {
+ target: u64,
+ },
+ PossibleValue {
+ value: u64,
+ },
+ // TODO: This is weird, you pass the value type as the text, we should restrict this behavior and type it
+ PossibleValueType,
+ ArrayIndex {
+ index: u64,
+ },
+ Indentation,
+ UnknownMemory,
+ EnumerationMember {
+ value: u64,
+ // TODO: Document where this type id comes from
+ // TODO: Can we type this to something other than a string?
+ /// The enumerations type id
+ type_id: Option<String>,
+ },
+ /// Operations like +, -, %
+ Operation,
+ BaseStructureName,
+ BaseStructureSeparator,
+ Brace {
+ // TODO: Explain what this is
+ hash: Option<u64>,
+ },
+ CodeSymbol {
+ // TODO: Value of what?
+ value: u64,
+ // TODO: Size of what?
+ size: usize, // TODO: Operand?
+ },
+ DataSymbol {
+ // TODO: Value of what?
+ value: u64,
+ // TODO: Size of what?
+ size: usize, // TODO: Operand?
+ },
+ LocalVariable {
+ // This comes from the token.value
+ // TODO: Do we have a variable id type we can attach to this?
+ // TODO: Probably not considering this is used at multiple IL levels.
+ variable_id: u64,
+ /// NOTE: This is only valid in SSA form
+ ssa_version: usize,
+ },
+ Import {
+ // TODO: Looks to be the target address from the import.
+ target: u64,
+ },
+ AddressDisplay {
+ address: u64,
+ },
+ // TODO: BAD
+ IndirectImport {
+ /// The address of the import
+ ///
+ /// If you want the address of the import token use [`InstructionTextToken::address`] instead.
+ target: u64,
+ /// Size of the instruction this token is apart of
+ size: usize,
+ // TODO: Type this
+ source_operand: usize,
+ },
+ ExternalSymbol {
+ // TODO: Value of what?
+ value: u64,
+ },
+ StackVariable {
+ // TODO: Do we have a variable id type we can attach to this?
+ // TODO: Probably not considering this is used at multiple IL levels.
+ variable_id: u64,
+ },
+ AddressSeparator,
+ CollapsedInformation,
+ CollapseStateIndicator {
+ // TODO: Explain what this is
+ hash: Option<u64>,
+ },
+}
- pub fn count(&self) -> usize {
- self.0.count
+impl InstructionTextTokenKind {
+ pub(crate) fn from_raw(value: &BNInstructionTextToken) -> Self {
+ match value.type_ {
+ BNInstructionTextTokenType::TextToken => Self::Text,
+ BNInstructionTextTokenType::InstructionToken => Self::Instruction,
+ BNInstructionTextTokenType::OperandSeparatorToken => Self::OperandSeparator,
+ BNInstructionTextTokenType::RegisterToken => Self::Register,
+ BNInstructionTextTokenType::IntegerToken => Self::Integer {
+ value: value.value,
+ size: match value.size {
+ 0 => None,
+ size => Some(size),
+ },
+ },
+ BNInstructionTextTokenType::PossibleAddressToken => Self::PossibleAddress {
+ value: value.value,
+ size: match value.size {
+ 0 => None,
+ size => Some(size),
+ },
+ },
+ BNInstructionTextTokenType::BeginMemoryOperandToken => Self::BeginMemoryOperand,
+ BNInstructionTextTokenType::EndMemoryOperandToken => Self::EndMemoryOperand,
+ BNInstructionTextTokenType::FloatingPointToken => Self::FloatingPoint {
+ value: value.value as f64,
+ size: match value.size {
+ 0 => None,
+ size => Some(size),
+ },
+ },
+ BNInstructionTextTokenType::AnnotationToken => Self::Annotation,
+ BNInstructionTextTokenType::CodeRelativeAddressToken => Self::CodeRelativeAddress {
+ value: value.value,
+ size: match value.size {
+ 0 => None,
+ size => Some(size),
+ },
+ },
+ BNInstructionTextTokenType::ArgumentNameToken => {
+ Self::ArgumentName { value: value.value }
+ }
+ BNInstructionTextTokenType::HexDumpByteValueToken => Self::HexDumpByteValue {
+ value: value.value as u8,
+ },
+ BNInstructionTextTokenType::HexDumpSkippedByteToken => Self::HexDumpSkippedByte,
+ BNInstructionTextTokenType::HexDumpInvalidByteToken => Self::HexDumpInvalidByte,
+ BNInstructionTextTokenType::HexDumpTextToken => {
+ Self::HexDumpText { width: value.value }
+ }
+ BNInstructionTextTokenType::OpcodeToken => Self::Opcode,
+ BNInstructionTextTokenType::StringToken => Self::String {
+ ty: match value.value {
+ 0 => StringType::AsciiString,
+ 1 => StringType::Utf8String,
+ 2 => StringType::Utf16String,
+ 3 => StringType::Utf32String,
+ _ => unreachable!(),
+ },
+ },
+ BNInstructionTextTokenType::CharacterConstantToken => Self::CharacterConstant,
+ BNInstructionTextTokenType::KeywordToken => Self::Keyword,
+ BNInstructionTextTokenType::TypeNameToken => Self::TypeName,
+ BNInstructionTextTokenType::FieldNameToken => Self::FieldName {
+ offset: value.value,
+ type_names: {
+ // NOTE: Do not need to free, this is a part of the From<&> impl
+ let raw_names =
+ unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
+ raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
+ },
+ },
+ BNInstructionTextTokenType::NameSpaceToken => Self::NameSpace,
+ BNInstructionTextTokenType::NameSpaceSeparatorToken => Self::NameSpaceSeparator,
+ BNInstructionTextTokenType::TagToken => Self::Tag,
+ BNInstructionTextTokenType::StructOffsetToken => Self::StructOffset {
+ offset: value.value,
+ type_names: {
+ // NOTE: Do not need to free, this is a part of the From<&> impl
+ let raw_names =
+ unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
+ raw_names.iter().filter_map(|&r| raw_to_string(r)).collect()
+ },
+ },
+ BNInstructionTextTokenType::StructOffsetByteValueToken => Self::StructOffsetByteValue,
+ BNInstructionTextTokenType::StructureHexDumpTextToken => {
+ Self::StructureHexDumpText { width: value.value }
+ }
+ BNInstructionTextTokenType::GotoLabelToken => Self::GotoLabel {
+ target: value.value,
+ },
+ BNInstructionTextTokenType::CommentToken => Self::Comment {
+ target: value.value,
+ },
+ BNInstructionTextTokenType::PossibleValueToken => {
+ Self::PossibleValue { value: value.value }
+ }
+ // NOTE: See my comment about this type in [`Self::PossibleValueType`]
+ BNInstructionTextTokenType::PossibleValueTypeToken => Self::PossibleValueType,
+ BNInstructionTextTokenType::ArrayIndexToken => Self::ArrayIndex { index: value.value },
+ BNInstructionTextTokenType::IndentationToken => Self::Indentation,
+ BNInstructionTextTokenType::UnknownMemoryToken => Self::UnknownMemory,
+ BNInstructionTextTokenType::EnumerationMemberToken => Self::EnumerationMember {
+ value: value.value,
+ type_id: {
+ // NOTE: Type id comes from value.typeNames, it should be the first one (hence the .next)
+ // NOTE: Do not need to free, this is a part of the From<&> impl
+ let raw_names =
+ unsafe { std::slice::from_raw_parts(value.typeNames, value.namesCount) };
+ raw_names.iter().filter_map(|&r| raw_to_string(r)).next()
+ },
+ },
+ BNInstructionTextTokenType::OperationToken => Self::Operation,
+ BNInstructionTextTokenType::BaseStructureNameToken => Self::BaseStructureName,
+ BNInstructionTextTokenType::BaseStructureSeparatorToken => Self::BaseStructureSeparator,
+ BNInstructionTextTokenType::BraceToken => Self::Brace {
+ hash: match value.value {
+ 0 => None,
+ hash => Some(hash),
+ },
+ },
+ BNInstructionTextTokenType::CodeSymbolToken => Self::CodeSymbol {
+ value: value.value,
+ size: value.size,
+ },
+ BNInstructionTextTokenType::DataSymbolToken => Self::DataSymbol {
+ value: value.value,
+ size: value.size,
+ },
+ BNInstructionTextTokenType::LocalVariableToken => Self::LocalVariable {
+ variable_id: value.value,
+ ssa_version: value.operand,
+ },
+ BNInstructionTextTokenType::ImportToken => Self::Import {
+ target: value.value,
+ },
+ BNInstructionTextTokenType::AddressDisplayToken => Self::AddressDisplay {
+ address: value.value,
+ },
+ BNInstructionTextTokenType::IndirectImportToken => Self::IndirectImport {
+ target: value.value,
+ size: value.size,
+ source_operand: value.operand,
+ },
+ BNInstructionTextTokenType::ExternalSymbolToken => {
+ Self::ExternalSymbol { value: value.value }
+ }
+ BNInstructionTextTokenType::StackVariableToken => Self::StackVariable {
+ variable_id: value.value,
+ },
+ BNInstructionTextTokenType::AddressSeparatorToken => Self::AddressSeparator,
+ BNInstructionTextTokenType::CollapsedInformationToken => Self::CollapsedInformation,
+ BNInstructionTextTokenType::CollapseStateIndicatorToken => {
+ Self::CollapseStateIndicator {
+ hash: match value.value {
+ 0 => None,
+ hash => Some(hash),
+ },
+ }
+ }
+ }
}
- pub fn tag_count(&self) -> usize {
- self.0.tagCount
+ /// Mapping to the [`BNInstructionTextTokenType::value`] field.
+ fn try_value(&self) -> Option<u64> {
+ // TODO: Double check to make sure these are correct.
+ match self {
+ InstructionTextTokenKind::Integer { value, .. } => Some(*value),
+ InstructionTextTokenKind::PossibleAddress { value, .. } => Some(*value),
+ InstructionTextTokenKind::PossibleValue { value, .. } => Some(*value),
+ InstructionTextTokenKind::FloatingPoint { value, .. } => Some(*value as u64),
+ InstructionTextTokenKind::CodeRelativeAddress { value, .. } => Some(*value),
+ InstructionTextTokenKind::ArgumentName { value, .. } => Some(*value),
+ InstructionTextTokenKind::HexDumpByteValue { value, .. } => Some(*value as u64),
+ InstructionTextTokenKind::HexDumpText { width, .. } => Some(*width),
+ InstructionTextTokenKind::String { ty, .. } => Some(*ty as u64),
+ InstructionTextTokenKind::FieldName { offset, .. } => Some(*offset),
+ InstructionTextTokenKind::StructOffset { offset, .. } => Some(*offset),
+ InstructionTextTokenKind::StructureHexDumpText { width, .. } => Some(*width),
+ InstructionTextTokenKind::GotoLabel { target, .. } => Some(*target),
+ InstructionTextTokenKind::Comment { target, .. } => Some(*target),
+ InstructionTextTokenKind::ArrayIndex { index, .. } => Some(*index),
+ InstructionTextTokenKind::EnumerationMember { value, .. } => Some(*value),
+ InstructionTextTokenKind::LocalVariable { variable_id, .. } => Some(*variable_id),
+ InstructionTextTokenKind::Import { target, .. } => Some(*target),
+ InstructionTextTokenKind::AddressDisplay { address, .. } => Some(*address),
+ InstructionTextTokenKind::IndirectImport { target, .. } => Some(*target),
+ InstructionTextTokenKind::Brace { hash, .. } => *hash,
+ InstructionTextTokenKind::CodeSymbol { value, .. } => Some(*value),
+ InstructionTextTokenKind::DataSymbol { value, .. } => Some(*value),
+ InstructionTextTokenKind::ExternalSymbol { value, .. } => Some(*value),
+ InstructionTextTokenKind::StackVariable { variable_id, .. } => Some(*variable_id),
+ InstructionTextTokenKind::CollapseStateIndicator { hash, .. } => *hash,
+ _ => None,
+ }
}
- pub fn tokens(&self) -> Vec<InstructionTextToken> {
- unsafe {
- std::slice::from_raw_parts::<BNInstructionTextToken>(self.0.tokens, self.0.count)
- .iter()
- .map(|x| InstructionTextToken::from_raw(x).clone())
- .collect()
+ /// Mapping to the [`BNInstructionTextTokenType::size`] field.
+ fn try_size(&self) -> Option<usize> {
+ match self {
+ InstructionTextTokenKind::Integer { size, .. } => *size,
+ InstructionTextTokenKind::FloatingPoint { size, .. } => *size,
+ InstructionTextTokenKind::PossibleAddress { size, .. } => *size,
+ InstructionTextTokenKind::CodeRelativeAddress { size, .. } => *size,
+ InstructionTextTokenKind::CodeSymbol { size, .. } => Some(*size),
+ InstructionTextTokenKind::DataSymbol { size, .. } => Some(*size),
+ InstructionTextTokenKind::IndirectImport { size, .. } => Some(*size),
+ _ => None,
}
}
-}
-impl std::fmt::Display for DisassemblyTextLine {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- for token in self.tokens() {
- write!(f, "{}", token.text())?;
+ /// Mapping to the [`BNInstructionTextTokenType::operand`] field.
+ fn try_operand(&self) -> Option<usize> {
+ match self {
+ InstructionTextTokenKind::LocalVariable { ssa_version, .. } => Some(*ssa_version),
+ InstructionTextTokenKind::IndirectImport { source_operand, .. } => {
+ Some(*source_operand)
+ }
+ _ => None,
}
-
- Ok(())
}
-}
-impl From<Vec<InstructionTextToken>> for DisassemblyTextLine {
- fn from(tokens: Vec<InstructionTextToken>) -> Self {
- let mut tokens: Box<[_]> = tokens.into();
-
- // TODO: let (tokens_pointer, tokens_len, _) = unsafe { tokens.into_raw_parts() }; // Can't use for now...still a rust nightly feature
- let tokens_pointer = tokens.as_mut_ptr();
- let tokens_len = tokens.len();
- mem::forget(tokens);
-
- DisassemblyTextLine(BNDisassemblyTextLine {
- addr: 0,
- instrIndex: BN_INVALID_EXPR,
- tokens: tokens_pointer as *mut _,
- count: tokens_len,
- highlight: BNHighlightColor {
- style: BNHighlightColorStyle::StandardHighlightColor,
- color: BNHighlightStandardColor::NoHighlightColor,
- mixColor: BNHighlightStandardColor::NoHighlightColor,
- mix: 0,
- r: 0,
- g: 0,
- b: 0,
- alpha: 0,
- },
- tags: ptr::null_mut(),
- tagCount: 0,
- typeInfo: BNDisassemblyTextLineTypeInfo {
- hasTypeInfo: false,
- parentType: ptr::null_mut(),
- fieldIndex: usize::MAX,
- offset: 0,
- },
- })
+ /// Mapping to the [`BNInstructionTextTokenType::typeNames`] field.
+ fn try_type_names(&self) -> Option<Vec<String>> {
+ match self {
+ InstructionTextTokenKind::FieldName { type_names, .. } => Some(type_names.clone()),
+ InstructionTextTokenKind::StructOffset { type_names, .. } => Some(type_names.clone()),
+ InstructionTextTokenKind::EnumerationMember { type_id, .. } => {
+ Some(vec![type_id.clone()?])
+ }
+ _ => None,
+ }
}
}
-impl From<&Vec<&str>> for DisassemblyTextLine {
- fn from(string_tokens: &Vec<&str>) -> Self {
- let mut tokens: Box<[BNInstructionTextToken]> = string_tokens
- .iter()
- .map(|&token| InstructionTextToken::new(token, InstructionTextTokenContents::Text).into_raw())
- .collect();
-
- // let (tokens_pointer, tokens_len, _) = unsafe { tokens.into_raw_parts() }; // Can't use for now...still a rust nighly feature
- let tokens_pointer = tokens.as_mut_ptr();
- let tokens_len = tokens.len();
- mem::forget(tokens);
-
- DisassemblyTextLine(BNDisassemblyTextLine {
- addr: 0,
- instrIndex: BN_INVALID_EXPR,
- tokens: tokens_pointer as *mut _,
- count: tokens_len,
- highlight: BNHighlightColor {
- style: BNHighlightColorStyle::StandardHighlightColor,
- color: BNHighlightStandardColor::NoHighlightColor,
- mixColor: BNHighlightStandardColor::NoHighlightColor,
- mix: 0,
- r: 0,
- g: 0,
- b: 0,
- alpha: 0,
- },
- tags: ptr::null_mut(),
- tagCount: 0,
- typeInfo: BNDisassemblyTextLineTypeInfo {
- hasTypeInfo: false,
- parentType: ptr::null_mut(),
- fieldIndex: usize::MAX,
- offset: 0,
- },
- })
+impl From<InstructionTextTokenKind> for BNInstructionTextTokenType {
+ fn from(value: InstructionTextTokenKind) -> Self {
+ match value {
+ InstructionTextTokenKind::Text => BNInstructionTextTokenType::TextToken,
+ InstructionTextTokenKind::Instruction => BNInstructionTextTokenType::InstructionToken,
+ InstructionTextTokenKind::OperandSeparator => {
+ BNInstructionTextTokenType::OperandSeparatorToken
+ }
+ InstructionTextTokenKind::Register => BNInstructionTextTokenType::RegisterToken,
+ InstructionTextTokenKind::Integer { .. } => BNInstructionTextTokenType::IntegerToken,
+ InstructionTextTokenKind::PossibleAddress { .. } => {
+ BNInstructionTextTokenType::PossibleAddressToken
+ }
+ InstructionTextTokenKind::BeginMemoryOperand => {
+ BNInstructionTextTokenType::BeginMemoryOperandToken
+ }
+ InstructionTextTokenKind::EndMemoryOperand => {
+ BNInstructionTextTokenType::EndMemoryOperandToken
+ }
+ InstructionTextTokenKind::FloatingPoint { .. } => {
+ BNInstructionTextTokenType::FloatingPointToken
+ }
+ InstructionTextTokenKind::Annotation => BNInstructionTextTokenType::AnnotationToken,
+ InstructionTextTokenKind::CodeRelativeAddress { .. } => {
+ BNInstructionTextTokenType::CodeRelativeAddressToken
+ }
+ InstructionTextTokenKind::ArgumentName { .. } => {
+ BNInstructionTextTokenType::ArgumentNameToken
+ }
+ InstructionTextTokenKind::HexDumpByteValue { .. } => {
+ BNInstructionTextTokenType::HexDumpByteValueToken
+ }
+ InstructionTextTokenKind::HexDumpSkippedByte => {
+ BNInstructionTextTokenType::HexDumpSkippedByteToken
+ }
+ InstructionTextTokenKind::HexDumpInvalidByte => {
+ BNInstructionTextTokenType::HexDumpInvalidByteToken
+ }
+ InstructionTextTokenKind::HexDumpText { .. } => {
+ BNInstructionTextTokenType::HexDumpTextToken
+ }
+ InstructionTextTokenKind::Opcode => BNInstructionTextTokenType::OpcodeToken,
+ InstructionTextTokenKind::String { .. } => BNInstructionTextTokenType::StringToken,
+ InstructionTextTokenKind::CharacterConstant => {
+ BNInstructionTextTokenType::CharacterConstantToken
+ }
+ InstructionTextTokenKind::Keyword => BNInstructionTextTokenType::KeywordToken,
+ InstructionTextTokenKind::TypeName => BNInstructionTextTokenType::TypeNameToken,
+ InstructionTextTokenKind::FieldName { .. } => {
+ BNInstructionTextTokenType::FieldNameToken
+ }
+ InstructionTextTokenKind::NameSpace => BNInstructionTextTokenType::NameSpaceToken,
+ InstructionTextTokenKind::NameSpaceSeparator => {
+ BNInstructionTextTokenType::NameSpaceSeparatorToken
+ }
+ InstructionTextTokenKind::Tag => BNInstructionTextTokenType::TagToken,
+ InstructionTextTokenKind::StructOffset { .. } => {
+ BNInstructionTextTokenType::StructOffsetToken
+ }
+ InstructionTextTokenKind::StructOffsetByteValue => {
+ BNInstructionTextTokenType::StructOffsetByteValueToken
+ }
+ InstructionTextTokenKind::StructureHexDumpText { .. } => {
+ BNInstructionTextTokenType::StructureHexDumpTextToken
+ }
+ InstructionTextTokenKind::GotoLabel { .. } => {
+ BNInstructionTextTokenType::GotoLabelToken
+ }
+ InstructionTextTokenKind::Comment { .. } => BNInstructionTextTokenType::CommentToken,
+ InstructionTextTokenKind::PossibleValue { .. } => {
+ BNInstructionTextTokenType::PossibleValueToken
+ }
+ InstructionTextTokenKind::PossibleValueType => {
+ BNInstructionTextTokenType::PossibleValueTypeToken
+ }
+ InstructionTextTokenKind::ArrayIndex { .. } => {
+ BNInstructionTextTokenType::ArrayIndexToken
+ }
+ InstructionTextTokenKind::Indentation => BNInstructionTextTokenType::IndentationToken,
+ InstructionTextTokenKind::UnknownMemory => {
+ BNInstructionTextTokenType::UnknownMemoryToken
+ }
+ InstructionTextTokenKind::EnumerationMember { .. } => {
+ BNInstructionTextTokenType::EnumerationMemberToken
+ }
+ InstructionTextTokenKind::Operation => BNInstructionTextTokenType::OperationToken,
+ InstructionTextTokenKind::BaseStructureName => {
+ BNInstructionTextTokenType::BaseStructureNameToken
+ }
+ InstructionTextTokenKind::BaseStructureSeparator => {
+ BNInstructionTextTokenType::BaseStructureSeparatorToken
+ }
+ InstructionTextTokenKind::Brace { .. } => BNInstructionTextTokenType::BraceToken,
+ InstructionTextTokenKind::CodeSymbol { .. } => {
+ BNInstructionTextTokenType::CodeSymbolToken
+ }
+ InstructionTextTokenKind::DataSymbol { .. } => {
+ BNInstructionTextTokenType::DataSymbolToken
+ }
+ InstructionTextTokenKind::LocalVariable { .. } => {
+ BNInstructionTextTokenType::LocalVariableToken
+ }
+ InstructionTextTokenKind::Import { .. } => BNInstructionTextTokenType::ImportToken,
+ InstructionTextTokenKind::AddressDisplay { .. } => {
+ BNInstructionTextTokenType::AddressDisplayToken
+ }
+ InstructionTextTokenKind::IndirectImport { .. } => {
+ BNInstructionTextTokenType::IndirectImportToken
+ }
+ InstructionTextTokenKind::ExternalSymbol { .. } => {
+ BNInstructionTextTokenType::ExternalSymbolToken
+ }
+ InstructionTextTokenKind::StackVariable { .. } => {
+ BNInstructionTextTokenType::StackVariableToken
+ }
+ InstructionTextTokenKind::AddressSeparator => {
+ BNInstructionTextTokenType::AddressSeparatorToken
+ }
+ InstructionTextTokenKind::CollapsedInformation => {
+ BNInstructionTextTokenType::CollapsedInformationToken
+ }
+ InstructionTextTokenKind::CollapseStateIndicator { .. } => {
+ BNInstructionTextTokenType::CollapseStateIndicatorToken
+ }
+ }
}
}
-impl Default for DisassemblyTextLine {
- fn default() -> Self {
- DisassemblyTextLine(BNDisassemblyTextLine {
- addr: 0,
- instrIndex: BN_INVALID_EXPR,
- tokens: ptr::null_mut(),
- count: 0,
- highlight: BNHighlightColor {
- style: BNHighlightColorStyle::StandardHighlightColor,
- color: BNHighlightStandardColor::NoHighlightColor,
- mixColor: BNHighlightStandardColor::NoHighlightColor,
- mix: 0,
- r: 0,
- g: 0,
- b: 0,
- alpha: 0,
- },
- tags: ptr::null_mut(),
- tagCount: 0,
- typeInfo: BNDisassemblyTextLineTypeInfo {
- hasTypeInfo: false,
- parentType: ptr::null_mut(),
- fieldIndex: usize::MAX,
- offset: 0,
- },
- })
- }
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum InstructionTextTokenContext {
+ Normal,
+ LocalVariable,
+ DataVariable,
+ FunctionReturn,
+ InstructionAddress,
+ ILInstructionIndex,
+ ConstData,
+ /// Use only with [`InstructionTextTokenKind::String`]
+ ConstStringData,
+ /// Use only with [`InstructionTextTokenKind::String`]
+ StringReference,
+ /// Use only with [`InstructionTextTokenKind::String`]
+ StringDataVariable,
+ /// For displaying strings which aren't associated with an address
+ ///
+ /// Use only with [`InstructionTextTokenKind::String`]
+ StringDisplay,
+ /// Use only with [`InstructionTextTokenKind::CollapseStateIndicator`]
+ Collapsed,
+ /// Use only with [`InstructionTextTokenKind::CollapseStateIndicator`]
+ Expanded,
+ /// Use only with [`InstructionTextTokenKind::CollapseStateIndicator`]
+ CollapsiblePadding,
}
-impl Drop for DisassemblyTextLine {
- fn drop(&mut self) {
- if !self.0.tokens.is_null() {
- let ptr = core::ptr::slice_from_raw_parts_mut(self.0.tokens, self.0.count);
- let _ = unsafe { Box::from_raw(ptr) };
+impl From<BNInstructionTextTokenContext> for InstructionTextTokenContext {
+ fn from(value: BNInstructionTextTokenContext) -> Self {
+ match value {
+ BNInstructionTextTokenContext::NoTokenContext => Self::Normal,
+ BNInstructionTextTokenContext::LocalVariableTokenContext => Self::LocalVariable,
+ BNInstructionTextTokenContext::DataVariableTokenContext => Self::DataVariable,
+ BNInstructionTextTokenContext::FunctionReturnTokenContext => Self::FunctionReturn,
+ BNInstructionTextTokenContext::InstructionAddressTokenContext => {
+ Self::InstructionAddress
+ }
+ BNInstructionTextTokenContext::ILInstructionIndexTokenContext => {
+ Self::ILInstructionIndex
+ }
+ BNInstructionTextTokenContext::ConstDataTokenContext => Self::ConstData,
+ // For use with [`InstructionTextTokenKind::String`]
+ BNInstructionTextTokenContext::ConstStringDataTokenContext => Self::ConstStringData,
+ BNInstructionTextTokenContext::StringReferenceTokenContext => Self::StringReference,
+ BNInstructionTextTokenContext::StringDataVariableTokenContext => {
+ Self::StringDataVariable
+ }
+ BNInstructionTextTokenContext::StringDisplayTokenContext => Self::StringDisplay,
+ // For use with [`InstructionTextTokenKind::CollapseStateIndicator`]
+ BNInstructionTextTokenContext::ContentCollapsedContext => Self::Collapsed,
+ BNInstructionTextTokenContext::ContentExpandedContext => Self::Expanded,
+ BNInstructionTextTokenContext::ContentCollapsiblePadding => Self::CollapsiblePadding,
}
}
}
-impl CoreArrayProvider for DisassemblyTextLine {
- type Raw = BNDisassemblyTextLine;
- type Context = ();
- type Wrapped<'a> = &'a Self;
-}
-
-unsafe impl CoreArrayProviderInner for DisassemblyTextLine {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNFreeDisassemblyTextLines(raw, count)
- }
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- core::mem::transmute(raw)
+impl From<InstructionTextTokenContext> for BNInstructionTextTokenContext {
+ fn from(value: InstructionTextTokenContext) -> Self {
+ match value {
+ InstructionTextTokenContext::Normal => Self::NoTokenContext,
+ InstructionTextTokenContext::LocalVariable => Self::LocalVariableTokenContext,
+ InstructionTextTokenContext::DataVariable => Self::DataVariableTokenContext,
+ InstructionTextTokenContext::FunctionReturn => Self::FunctionReturnTokenContext,
+ InstructionTextTokenContext::InstructionAddress => Self::InstructionAddressTokenContext,
+ InstructionTextTokenContext::ILInstructionIndex => Self::ILInstructionIndexTokenContext,
+ InstructionTextTokenContext::ConstData => Self::ConstDataTokenContext,
+ InstructionTextTokenContext::ConstStringData => Self::ConstStringDataTokenContext,
+ InstructionTextTokenContext::StringReference => Self::StringReferenceTokenContext,
+ InstructionTextTokenContext::StringDataVariable => Self::StringDataVariableTokenContext,
+ InstructionTextTokenContext::StringDisplay => Self::StringDisplayTokenContext,
+ InstructionTextTokenContext::Collapsed => Self::ContentCollapsedContext,
+ InstructionTextTokenContext::Expanded => Self::ContentExpandedContext,
+ InstructionTextTokenContext::CollapsiblePadding => Self::ContentCollapsiblePadding,
+ }
}
}
-pub type DisassemblyOption = BNDisassemblyOption;
-
+// TODO: Make a builder for this.
#[derive(PartialEq, Eq, Hash)]
pub struct DisassemblySettings {
pub(crate) handle: *mut BNDisassemblySettings,
@@ -481,9 +969,7 @@ impl DisassemblySettings {
pub fn new() -> Ref<Self> {
unsafe {
let handle = BNCreateDisassemblySettings();
-
debug_assert!(!handle.is_null());
-
Ref::new(Self { handle })
}
}