summaryrefslogtreecommitdiff
path: root/rust/src/linearview.rs
diff options
context:
space:
mode:
authorFabian Freyer <fabian.freyer@physik.tu-berlin.de>2022-01-28 01:36:26 +0100
committerKyleMiles <krm504@nyu.edu>2022-02-14 18:45:11 -0500
commit6cd49edb317112acc73f7caeb285f4134a472d72 (patch)
tree3fc1af20b46dcb33c1ba5490193a0226e112e839 /rust/src/linearview.rs
parent181ad567199e5685578ecf7ad400257098c2e175 (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/linearview.rs')
-rw-r--r--rust/src/linearview.rs420
1 files changed, 420 insertions, 0 deletions
diff --git a/rust/src/linearview.rs b/rust/src/linearview.rs
new file mode 100644
index 00000000..a4221443
--- /dev/null
+++ b/rust/src/linearview.rs
@@ -0,0 +1,420 @@
+use binaryninjacore_sys::*;
+
+use crate::binaryview::BinaryView;
+use crate::disassembly::{DisassemblySettings, DisassemblyTextLine};
+use crate::function::Function;
+
+use crate::rc::*;
+use std::ops::Deref;
+
+use std::mem;
+
+pub struct LinearViewObject {
+ pub(crate) handle: *mut BNLinearViewObject,
+}
+
+impl LinearViewObject {
+ pub(crate) unsafe fn from_raw(handle: *mut BNLinearViewObject) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+
+ Ref::new(Self { handle })
+ }
+
+ pub fn data_only(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle =
+ binaryninjacore_sys::BNCreateLinearViewDataOnly(view.handle, settings.handle);
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn disassembly(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle =
+ binaryninjacore_sys::BNCreateLinearViewDisassembly(view.handle, settings.handle);
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn lifted_il(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle =
+ binaryninjacore_sys::BNCreateLinearViewLiftedIL(view.handle, settings.handle);
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn mlil(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle =
+ binaryninjacore_sys::BNCreateLinearViewMediumLevelIL(view.handle, settings.handle);
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn mlil_ssa(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewMediumLevelILSSAForm(
+ view.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn hlil(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle =
+ binaryninjacore_sys::BNCreateLinearViewHighLevelIL(view.handle, settings.handle);
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn hlil_ssa(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewHighLevelILSSAForm(
+ view.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn language_representation(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewLanguageRepresentation(
+ view.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn single_function_disassembly(
+ function: &Function,
+ settings: &DisassemblySettings,
+ ) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewSingleFunctionDisassembly(
+ function.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn single_function_lifted_il(
+ function: &Function,
+ settings: &DisassemblySettings,
+ ) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewSingleFunctionLiftedIL(
+ function.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn single_function_mlil(function: &Function, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewSingleFunctionMediumLevelIL(
+ function.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn single_function_mlil_ssa(
+ function: &Function,
+ settings: &DisassemblySettings,
+ ) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewSingleFunctionMediumLevelILSSAForm(
+ function.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn single_function_hlil(function: &Function, settings: &DisassemblySettings) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewSingleFunctionHighLevelIL(
+ function.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn single_function_hlil_ssa(
+ function: &Function,
+ settings: &DisassemblySettings,
+ ) -> Ref<Self> {
+ unsafe {
+ let handle = binaryninjacore_sys::BNCreateLinearViewSingleFunctionHighLevelILSSAForm(
+ function.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn single_function_language_representation(
+ function: &Function,
+ settings: &DisassemblySettings,
+ ) -> Ref<Self> {
+ unsafe {
+ let handle =
+ binaryninjacore_sys::BNCreateLinearViewSingleFunctionLanguageRepresentation(
+ function.handle,
+ settings.handle,
+ );
+
+ Self::from_raw(handle)
+ }
+ }
+}
+
+unsafe impl RefCountable for LinearViewObject {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: BNNewLinearViewObjectReference(handle.handle),
+ })
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeLinearViewObject(handle.handle);
+ }
+}
+
+impl ToOwned for LinearViewObject {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+unsafe impl Send for LinearViewObject {}
+unsafe impl Sync for LinearViewObject {}
+
+#[derive(Eq)]
+pub struct LinearViewCursor {
+ pub(crate) handle: *mut binaryninjacore_sys::BNLinearViewCursor,
+}
+
+impl LinearViewCursor {
+ pub(crate) unsafe fn from_raw(handle: *mut BNLinearViewCursor) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+
+ Ref::new(Self { handle })
+ }
+
+ pub fn new(root: &LinearViewObject) -> Ref<Self> {
+ unsafe {
+ let handle = BNCreateLinearViewCursor(root.handle);
+ Self::from_raw(handle)
+ }
+ }
+
+ /// Gets the current [LinearViewObject] associated with this cursor.
+ pub fn current_object(&self) -> Ref<LinearViewObject> {
+ unsafe {
+ let handle = BNGetLinearViewCursorCurrentObject(self.handle);
+ LinearViewObject::from_raw(handle)
+ }
+ }
+
+ // FIXME: can we implement clone without shadowing ToOwned?
+ pub fn duplicate(&self) -> Ref<Self> {
+ unsafe {
+ let handle = BNDuplicateLinearViewCursor(self.handle);
+ Self::from_raw(handle)
+ }
+ }
+
+ pub fn before_begin(&self) -> bool {
+ unsafe { BNIsLinearViewCursorBeforeBegin(self.handle) }
+ }
+
+ pub fn after_end(&self) -> bool {
+ unsafe { BNIsLinearViewCursorAfterEnd(self.handle) }
+ }
+
+ pub fn valid(&self) -> bool {
+ !(self.before_begin() || self.after_end())
+ }
+
+ pub fn seek_to_start(&self) {
+ unsafe { BNSeekLinearViewCursorToBegin(self.handle) }
+ }
+
+ pub fn seek_to_end(&self) {
+ unsafe { BNSeekLinearViewCursorToEnd(self.handle) }
+ }
+
+ pub fn seek_to_address(&self, address: u64) {
+ unsafe { BNSeekLinearViewCursorToAddress(self.handle, address) }
+ }
+
+ pub fn ordering_index(&self) -> std::ops::Range<u64> {
+ unsafe {
+ let range = BNGetLinearViewCursorOrderingIndex(self.handle);
+ range.start..range.end
+ }
+ }
+
+ pub fn ordering_index_total(&self) -> u64 {
+ unsafe { BNGetLinearViewCursorOrderingIndexTotal(self.handle) }
+ }
+
+ pub fn seek_to_ordering_index(&self, idx: u64) {
+ unsafe { BNSeekLinearViewCursorToAddress(self.handle, idx) }
+ }
+
+ pub fn previous(&self) -> bool {
+ unsafe { BNLinearViewCursorPrevious(self.handle) }
+ }
+
+ pub fn next(&self) -> bool {
+ unsafe { BNLinearViewCursorNext(self.handle) }
+ }
+
+ pub fn lines(&self) -> Array<LinearDisassemblyLine> {
+ let mut count: usize = 0;
+ unsafe {
+ let handles = BNGetLinearViewCursorLines(self.handle, &mut count);
+ Array::new(handles, count, ())
+ }
+ }
+}
+
+impl PartialEq for LinearViewCursor {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe { BNCompareLinearViewCursors(self.handle, other.handle) == 0 }
+ }
+}
+
+impl PartialOrd for LinearViewCursor {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ match unsafe { BNCompareLinearViewCursors(self.handle, other.handle) } {
+ i if i < 0 => Some(std::cmp::Ordering::Less),
+ i if i > 0 => Some(std::cmp::Ordering::Greater),
+ _ => Some(std::cmp::Ordering::Equal),
+ }
+ }
+}
+
+impl Ord for LinearViewCursor {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ match unsafe { BNCompareLinearViewCursors(self.handle, other.handle) } {
+ i if i < 0 => std::cmp::Ordering::Less,
+ i if i > 0 => std::cmp::Ordering::Greater,
+ _ => std::cmp::Ordering::Equal,
+ }
+ }
+}
+
+unsafe impl RefCountable for LinearViewCursor {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: BNNewLinearViewCursorReference(handle.handle),
+ })
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeLinearViewCursor(handle.handle);
+ }
+}
+
+impl ToOwned for LinearViewCursor {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+unsafe impl Send for LinearViewCursor {}
+unsafe impl Sync for LinearViewCursor {}
+
+pub type LinearDisassemblyLineType = BNLinearDisassemblyLineType;
+
+pub struct LinearDisassemblyLine {
+ t: LinearDisassemblyLineType,
+
+ // These will be cleaned up by BNFreeLinearDisassemblyLines, so we
+ // don't drop them in the relevant deconstructors.
+ function: mem::ManuallyDrop<Ref<Function>>,
+ contents: mem::ManuallyDrop<DisassemblyTextLine>,
+}
+
+impl LinearDisassemblyLine {
+ pub(crate) unsafe fn from_raw(raw: &BNLinearDisassemblyLine) -> Self {
+ let linetype = raw.type_;
+ let function = mem::ManuallyDrop::new(Function::from_raw(raw.function));
+ let contents = mem::ManuallyDrop::new(DisassemblyTextLine(raw.contents));
+ Self {
+ t: linetype,
+ function,
+ contents,
+ }
+ }
+
+ pub fn function(&self) -> &Function {
+ self.function.as_ref()
+ }
+
+ pub fn line_type(&self) -> LinearDisassemblyLineType {
+ self.t
+ }
+}
+
+impl Deref for LinearDisassemblyLine {
+ type Target = DisassemblyTextLine;
+ fn deref(&self) -> &Self::Target {
+ self.contents.deref()
+ }
+}
+
+impl std::fmt::Display for LinearDisassemblyLine {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.deref())
+ }
+}
+
+impl CoreArrayProvider for LinearDisassemblyLine {
+ type Raw = BNLinearDisassemblyLine;
+ type Context = ();
+}
+
+unsafe impl CoreOwnedArrayProvider for LinearDisassemblyLine {
+ unsafe fn free(raw: *mut BNLinearDisassemblyLine, count: usize, _context: &()) {
+ BNFreeLinearDisassemblyLines(raw, count);
+ }
+}
+
+unsafe impl<'a> CoreArrayWrapper<'a> for LinearDisassemblyLine {
+ type Wrapped = Guard<'a, LinearDisassemblyLine>;
+
+ unsafe fn wrap_raw(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped {
+ Guard::new(LinearDisassemblyLine::from_raw(raw), _context)
+ }
+}