diff options
| author | KyleMiles <krm504@nyu.edu> | 2022-02-14 18:41:40 -0500 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2022-02-14 18:45:16 -0500 |
| commit | 2845ba6208ce3c29998a48df5073ed15a11ead77 (patch) | |
| tree | 7a50af1833dae6d4acaba420f714374fa8421dff /rust/src | |
| parent | 6cd49edb317112acc73f7caeb285f4134a472d72 (diff) | |
Rust: Minor tweaks to 2890; merge architecture::InstructionTextToken and disassembly::InstructionTextToken; update examples
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/architecture.rs | 166 | ||||
| -rw-r--r-- | rust/src/binaryview.rs | 6 | ||||
| -rw-r--r-- | rust/src/disassembly.rs | 130 | ||||
| -rw-r--r-- | rust/src/rc.rs | 5 |
4 files changed, 132 insertions, 175 deletions
diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 7ce672b8..b8e40c5b 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -27,6 +27,7 @@ use std::ptr; use std::slice; use crate::callingconvention::CallingConvention; +use crate::disassembly::InstructionTextToken; use crate::platform::Platform; use crate::{BranchType, Endianness}; @@ -161,128 +162,6 @@ impl InstructionInfo { } } -#[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), -} - -pub use binaryninjacore_sys::BNInstructionTextTokenContext as InstructionTextTokenContext; - -#[repr(C)] -pub struct InstructionTextToken(BNInstructionTextToken); -impl InstructionTextToken { - pub fn new<T: Into<Vec<u8>>>(contents: InstructionTextTokenContents, text: T) -> Self { - use self::BNInstructionTextTokenType::*; - use self::InstructionTextTokenContents::*; - - let mut res: BNInstructionTextToken = unsafe { zeroed() }; - - res.context = InstructionTextTokenContext::NoTokenContext; - res.address = 0; - res.size = 0; // TODO supply? x86 seems to, others don't... - res.operand = 0xffff_ffff; - res.confidence = 0xff; - - match contents { - Integer(v) => res.value = v, - PossibleAddress(v) | CodeRelativeAddress(v) => { - res.value = v; - res.address = v; - } - _ => {} - } - - res.type_ = match contents { - Text => TextToken, - Instruction => InstructionToken, - OperandSeparator => OperandSeparatorToken, - Register => RegisterToken, - Integer(_) => IntegerToken, - PossibleAddress(_) => PossibleAddressToken, - BeginMemoryOperand => BeginMemoryOperandToken, - EndMemoryOperand => EndMemoryOperandToken, - FloatingPoint => FloatingPointToken, - CodeRelativeAddress(_) => CodeRelativeAddressToken, - }; - - res.text = CString::new(text).unwrap().into_raw(); - - InstructionTextToken(res) - } - - pub fn text(&self) -> &CStr { - unsafe { CStr::from_ptr(self.0.text) } - } - - pub fn contents(&self) -> InstructionTextTokenContents { - use self::BNInstructionTextTokenType::*; - use self::InstructionTextTokenContents::*; - - 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"), - } - } - - pub fn context(&self) -> InstructionTextTokenContext { - self.0.context - } - - pub fn size(&self) -> usize { - self.0.size - } - - pub fn operand(&self) -> usize { - self.0.operand - } - - pub fn address(&self) -> u64 { - self.0.address - } -} - -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, - width: 0, - text: self.text().to_owned().into_raw(), - confidence: 0xff, - typeNames: ptr::null_mut(), - namesCount: 0, - }) - } -} - -impl Drop for InstructionTextToken { - fn drop(&mut self) { - let _owned = unsafe { CString::from_raw(self.0.text) }; - } -} - pub use binaryninjacore_sys::BNFlagRole as FlagRole; pub use binaryninjacore_sys::BNImplicitRegisterExtend as ImplicitRegisterExtend; pub use binaryninjacore_sys::BNLowLevelILFlagCondition as FlagCondition; @@ -395,8 +274,6 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> { type FlagClass: FlagClass; type FlagGroup: FlagGroup<FlagType = Self::Flag, FlagClass = Self::FlagClass>; - type InstructionTextContainer: Into<Vec<InstructionTextToken>>; - fn endianness(&self) -> Endianness; fn address_size(&self) -> usize; fn default_integer_size(&self) -> usize; @@ -411,7 +288,7 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> { &self, data: &[u8], addr: u64, - ) -> Option<(usize, Self::InstructionTextContainer)>; + ) -> Option<(usize, Array<InstructionTextToken>)>; fn instruction_llil( &self, data: &[u8], @@ -769,28 +646,6 @@ impl Drop for CoreArchitectureList { } } -pub struct InstructionTextTokenList(*mut BNInstructionTextToken, usize); - -impl ops::Deref for InstructionTextTokenList { - type Target = [InstructionTextToken]; - - fn deref(&self) -> &Self::Target { - unsafe { slice::from_raw_parts(&*(self.0 as *const InstructionTextToken), self.1) } - } -} - -impl Drop for InstructionTextTokenList { - fn drop(&mut self) { - unsafe { BNFreeInstructionText(self.0, self.1) } - } -} - -impl Into<Vec<InstructionTextToken>> for InstructionTextTokenList { - fn into(self) -> Vec<InstructionTextToken> { - self.to_vec() - } -} - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CoreArchitecture(pub(crate) *mut BNArchitecture); @@ -844,8 +699,6 @@ impl Architecture for CoreArchitecture { type FlagClass = CoreFlagClass; type FlagGroup = CoreFlagGroup; - type InstructionTextContainer = InstructionTextTokenList; - fn endianness(&self) -> Endianness { unsafe { BNGetArchitectureEndianness(self.0) } } @@ -899,7 +752,7 @@ impl Architecture for CoreArchitecture { &self, data: &[u8], addr: u64, - ) -> Option<(usize, InstructionTextTokenList)> { + ) -> Option<(usize, Array<InstructionTextToken>)> { let mut consumed = data.len(); let mut count: usize = 0; let mut result: *mut BNInstructionTextToken = ptr::null_mut(); @@ -913,7 +766,7 @@ impl Architecture for CoreArchitecture { &mut result as *mut _, &mut count as *mut _, ) { - Some((consumed, InstructionTextTokenList(result, count))) + Some((consumed, Array::new(result, count, ()))) } else { None } @@ -1382,15 +1235,10 @@ where match custom_arch.instruction_text(data, addr) { Some((res_size, res_tokens)) => { unsafe { - let mut res_tokens = res_tokens.into(); - res_tokens.shrink_to_fit(); - assert!(res_tokens.capacity() == res_tokens.len()); - + let (r_ptr, r_count) = res_tokens.into_raw_parts(); + *result = r_ptr; + *count = r_count; *len = res_size; - *count = res_tokens.len(); - - *result = res_tokens.as_mut_ptr() as *mut _; - mem::forget(res_tokens); } true } diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 6d52fa88..5209f744 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -784,7 +784,7 @@ pub trait BinaryViewExt: BinaryViewBase { /// repeatedly to get more lines of linear disassembly. /// /// # Arguments - /// * `pos` - Position to start retrieving linear disassembly lines from + /// * `pos` - Position to retrieve linear disassembly lines from fn get_next_linear_disassembly_lines( &self, pos: &mut LinearViewCursor, @@ -801,14 +801,14 @@ pub trait BinaryViewExt: BinaryViewBase { result } - /// Retrieves a list of the next disassembly lines. + /// Retrieves a list of the previous disassembly lines. /// /// `get_previous_linear_disassembly_lines` retrieves an [Array] over [LinearDisassemblyLine] objects for the /// previous disassembly lines, and updates the [LinearViewCursor] passed in. This function can be called /// repeatedly to get more lines of linear disassembly. /// /// # Arguments - /// * `pos` - Position to start retrieving linear disassembly lines from + /// * `pos` - Position to retrieve linear disassembly lines relative to fn get_previous_linear_disassembly_lines( &self, pos: &mut LinearViewCursor, diff --git a/rust/src/disassembly.rs b/rust/src/disassembly.rs index 6266597c..ff00e8d0 100644 --- a/rust/src/disassembly.rs +++ b/rust/src/disassembly.rs @@ -28,30 +28,73 @@ use std::ptr; pub type InstructionTextTokenType = BNInstructionTextTokenType; pub type InstructionTextTokenContext = BNInstructionTextTokenContext; +#[repr(C)] pub struct InstructionTextToken(pub(crate) BNInstructionTextToken); -// TODO : Consider remodeling this after types::EnumerationMember +#[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), +} + impl InstructionTextToken { - // TODO : New vs new_with_value ? pub(crate) unsafe fn from_raw(raw: &BNInstructionTextToken) -> Self { Self(raw.clone()) } - pub fn new(type_: InstructionTextTokenType, text: &str, value: u64) -> Self { - let raw_name = BnString::new(text); + pub fn new(text: BnString, contents: InstructionTextTokenContents) -> Self { + let (value, address) = match contents { + InstructionTextTokenContents::Integer(v) => (v, 0), + InstructionTextTokenContents::PossibleAddress(v) + | InstructionTextTokenContents::CodeRelativeAddress(v) => (v, v), + _ => (0, 0), + }; + + 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 + } + }; - // TODO : Maybe impl Drop for this newtype and perhaps call from_raw for the BnString..I think it's a memory leak otherwise + let width = text.len() as u64; InstructionTextToken(BNInstructionTextToken { - type_: type_, - text: raw_name.into_raw(), - value: value, - width: text.chars().count() as u64, + type_, + text: text.into_raw(), + value, + width, size: 0, - operand: 0xffffffff, + operand: 0xffff_ffff, context: InstructionTextTokenContext::NoTokenContext, confidence: BN_FULL_CONFIDENCE, - address: 0, + address, typeNames: ptr::null_mut(), namesCount: 0, }) @@ -68,6 +111,41 @@ impl InstructionTextToken { pub fn text(&self) -> &BnStr { unsafe { BnStr::from_raw(self.0.text) } } + + pub fn contents(&self) -> InstructionTextTokenContents { + use self::BNInstructionTextTokenType::*; + use self::InstructionTextTokenContents::*; + + 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"), + } + } + + pub fn context(&self) -> InstructionTextTokenContext { + self.0.context + } + + pub fn size(&self) -> usize { + self.0.size + } + + pub fn operand(&self) -> usize { + self.0.operand + } + + pub fn address(&self) -> u64 { + self.0.address + } } impl Default for InstructionTextToken { @@ -88,6 +166,32 @@ impl Default for InstructionTextToken { } } +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, + width: 0, + text: BnString::new(self.text()).into_raw(), + confidence: 0xff, + typeNames: ptr::null_mut(), + namesCount: 0, + }) + } +} + +// TODO : There is almost certainly a memory leak here - in the case where +// `impl CoreOwnedArrayProvider for InstructionTextToken` doesn't get triggered +// impl Drop for InstructionTextToken { +// fn drop(&mut self) { +// let _owned = unsafe { BnString::from_raw(self.0.text) }; +// } +// } + impl CoreArrayProvider for InstructionTextToken { type Raw = BNInstructionTextToken; type Context = (); @@ -198,8 +302,8 @@ impl From<Vec<InstructionTextToken>> for DisassemblyTextLine { impl From<&Vec<&str>> for DisassemblyTextLine { fn from(string_tokens: &Vec<&str>) -> Self { let mut tokens: Vec<BNInstructionTextToken> = Vec::with_capacity(string_tokens.len()); - tokens.extend(string_tokens.iter().map(|token| { - InstructionTextToken::new(InstructionTextTokenType::TextToken, token, 0).0 + tokens.extend(string_tokens.iter().map(|&token| { + InstructionTextToken::new(BnString::new(token), InstructionTextTokenContents::Text).0 })); assert!(tokens.len() == tokens.capacity()); diff --git a/rust/src/rc.rs b/rust/src/rc.rs index bc60bf94..a55c46d2 100644 --- a/rust/src/rc.rs +++ b/rust/src/rc.rs @@ -197,6 +197,11 @@ impl<P: CoreOwnedArrayProvider> Array<P> { pub fn len(&self) -> usize { self.count } + + pub fn into_raw_parts(self) -> (*mut P::Raw, usize) { + let me = mem::ManuallyDrop::new(self); + (me.contents, me.count) + } } impl<'a, P: 'a + CoreArrayWrapper<'a> + CoreOwnedArrayProvider> Array<P> { |
