summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2022-02-14 18:41:40 -0500
committerKyleMiles <krm504@nyu.edu>2022-02-14 18:45:16 -0500
commit2845ba6208ce3c29998a48df5073ed15a11ead77 (patch)
tree7a50af1833dae6d4acaba420f714374fa8421dff /rust/src
parent6cd49edb317112acc73f7caeb285f4134a472d72 (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.rs166
-rw-r--r--rust/src/binaryview.rs6
-rw-r--r--rust/src/disassembly.rs130
-rw-r--r--rust/src/rc.rs5
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> {