diff options
| author | Fabian Freyer <fabian.freyer@physik.tu-berlin.de> | 2022-01-28 01:36:26 +0100 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2022-02-14 18:45:11 -0500 |
| commit | 6cd49edb317112acc73f7caeb285f4134a472d72 (patch) | |
| tree | 3fc1af20b46dcb33c1ba5490193a0226e112e839 /rust/src/disassembly.rs | |
| parent | 181ad567199e5685578ecf7ad400257098c2e175 (diff) | |
rust: add linearview and related APIs
This should include everything required to retrieve linear disassembly
for a function.
* add `highest_address` method to `Function`
* add `DisassemblySettings`
* add text getter for `InstructionTextToken`
* add `LinearViewObject`, `LinearViewCursor`
* add decompilation example
Diffstat (limited to 'rust/src/disassembly.rs')
| -rw-r--r-- | rust/src/disassembly.rs | 118 |
1 files changed, 116 insertions, 2 deletions
diff --git a/rust/src/disassembly.rs b/rust/src/disassembly.rs index 8edf3c4f..6266597c 100644 --- a/rust/src/disassembly.rs +++ b/rust/src/disassembly.rs @@ -16,9 +16,11 @@ use binaryninjacore_sys::*; -use crate::string::BnString; +use crate::string::{BnStr, BnString}; use crate::{BN_FULL_CONFIDENCE, BN_INVALID_EXPR}; +use crate::rc::*; + use std::convert::From; use std::mem; use std::ptr; @@ -31,6 +33,9 @@ pub struct InstructionTextToken(pub(crate) BNInstructionTextToken); // TODO : Consider remodeling this after types::EnumerationMember 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); @@ -59,6 +64,10 @@ impl InstructionTextToken { pub fn set_context(&mut self, context: InstructionTextTokenContext) { self.0.context = context; } + + pub fn text(&self) -> &BnStr { + unsafe { BnStr::from_raw(self.0.text) } + } } impl Default for InstructionTextToken { @@ -79,21 +88,73 @@ impl Default for InstructionTextToken { } } +impl CoreArrayProvider for InstructionTextToken { + type Raw = BNInstructionTextToken; + type Context = (); +} + +unsafe impl CoreOwnedArrayProvider for InstructionTextToken { + unsafe fn free(raw: *mut BNInstructionTextToken, count: usize, _context: &()) { + BNFreeInstructionText(raw, count); + } +} + +unsafe impl<'a> CoreArrayWrapper<'a> for InstructionTextToken { + type Wrapped = Guard<'a, InstructionTextToken>; + + unsafe fn wrap_raw(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped { + Guard::new(InstructionTextToken::from_raw(raw), _context) + } +} + 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 + } + + pub fn count(&self) -> usize { + self.0.count + } + + pub fn tag_count(&self) -> usize { + self.0.tagCount + } + + pub fn tokens(&self) -> ArrayGuard<InstructionTextToken> { + unsafe { ArrayGuard::new(self.0.tokens, self.0.count, ()) } + } +} + +impl std::fmt::Display for DisassemblyTextLine { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let tokens: Vec<InstructionTextToken> = unsafe { Vec::from_raw_parts(self.0.tokens as *mut _, self.0.count, self.0.count) }; for token in &tokens { let token_string = unsafe { BnString::from_raw(token.0.text) }; - print!("{}", token_string); + let result = write!(f, "{}", token_string); token_string.into_raw(); + + if result.is_err() { + mem::forget(tokens); + return result; + } } mem::forget(tokens); + + Ok(()) } } @@ -210,3 +271,56 @@ impl Drop for DisassemblyTextLine { } } } + +pub type DisassemblyOption = BNDisassemblyOption; + +#[derive(PartialEq, Eq, Hash)] +pub struct DisassemblySettings { + pub(crate) handle: *mut BNDisassemblySettings, +} + +impl DisassemblySettings { + pub fn new() -> Ref<Self> { + unsafe { + let handle = BNCreateDisassemblySettings(); + + debug_assert!(!handle.is_null()); + + Ref::new(Self { handle }) + } + } + + pub fn set_option(&self, option: DisassemblyOption, state: bool) { + unsafe { BNSetDisassemblySettingsOption(self.handle, option, state) } + } + + pub fn is_option_set(&self, option: DisassemblyOption) -> bool { + unsafe { BNIsDisassemblySettingsOptionSet(self.handle, option) } + } +} + +impl AsRef<DisassemblySettings> for DisassemblySettings { + fn as_ref(&self) -> &Self { + self + } +} + +impl ToOwned for DisassemblySettings { + type Owned = Ref<Self>; + + fn to_owned(&self) -> Self::Owned { + unsafe { RefCountable::inc_ref(self) } + } +} + +unsafe impl RefCountable for DisassemblySettings { + unsafe fn inc_ref(handle: &Self) -> Ref<Self> { + Ref::new(Self { + handle: BNNewDisassemblySettingsReference(handle.handle), + }) + } + + unsafe fn dec_ref(handle: &Self) { + BNFreeDisassemblySettings(handle.handle); + } +} |
