summaryrefslogtreecommitdiff
path: root/rust/src/segment.rs
diff options
context:
space:
mode:
authorRyan Snyder <ryan@vector35.com>2021-01-21 18:27:48 +0000
committerKyleMiles <krm504@nyu.edu>2021-01-21 19:06:55 +0000
commitd3140edec185f47235b9e4642bdd56d6c585a341 (patch)
treea61859c29e4e3539daea2b761bb1439d942beaf4 /rust/src/segment.rs
parentc0ddbf0c76d3f1bb7a2b2024f749afc8b9482575 (diff)
This is a combination of 23 commits, the work of Ryan Snyder:
Initial fresh repo Add support for recent calling convention API updates and folds the binaryninjacore-sys crate directly into this one. Add support for auto function analysis suppression Finish moving binaryninjacore-sys back into this crate Update for Symbol/Segment core API changes Update for Symbol API cleanup api: advance submodule reference, support Token changes arch/lifting: support for flags in custom architectures arch/lifting: support default flag write behaviors, handle more ops build: enable headless binary support on MacOS via evil hack bv: add BinaryView wrapper support, remove wrong comment api: update to latest binja dev branch support deps: bump dep versions rust: bump to 2018 edition api: bump to avoid cargo submodule brokenness build: improve binaryninja path detection; enable linux linkhack bv: stub for bv load settings arch: fix flag related crash, minor llil update api: update for recent changes macos: disable linkhack briefly
Diffstat (limited to 'rust/src/segment.rs')
-rw-r--r--rust/src/segment.rs190
1 files changed, 190 insertions, 0 deletions
diff --git a/rust/src/segment.rs b/rust/src/segment.rs
new file mode 100644
index 00000000..0985d0d3
--- /dev/null
+++ b/rust/src/segment.rs
@@ -0,0 +1,190 @@
+use binaryninjacore_sys::*;
+
+
+use std::ops::Range;
+
+use crate::binaryview::BinaryView;
+use crate::rc::*;
+
+fn set_bit(val: u32, bit_mask: u32, new_val: bool) -> u32 {
+ (val & !bit_mask) | if new_val { bit_mask } else { 0 }
+}
+
+#[must_use]
+pub struct SegmentBuilder {
+ ea: Range<u64>,
+ parent_backing: Option<Range<u64>>,
+ flags: u32,
+ is_auto: bool,
+}
+
+impl SegmentBuilder {
+ pub fn parent_backing(mut self, parent_backing: Range<u64>) -> Self {
+ self.parent_backing = Some(parent_backing);
+ self
+ }
+
+ pub fn executable(mut self, executable: bool) -> Self {
+ self.flags = set_bit(self.flags, 0x01, executable);
+ self
+ }
+
+ pub fn writable(mut self, writable: bool) -> Self {
+ self.flags = set_bit(self.flags, 0x02, writable);
+ self
+ }
+
+ pub fn readable(mut self, readable: bool) -> Self {
+ self.flags = set_bit(self.flags, 0x04, readable);
+ self
+ }
+
+ pub fn contains_data(mut self, contains_data: bool) -> Self {
+ self.flags = set_bit(self.flags, 0x08, contains_data);
+ self
+ }
+
+ pub fn contains_code(mut self, contains_code: bool) -> Self {
+ self.flags = set_bit(self.flags, 0x10, contains_code);
+ self
+ }
+
+ pub fn deny_write(mut self, deny_write: bool) -> Self {
+ self.flags = set_bit(self.flags, 0x20, deny_write);
+ self
+ }
+
+ pub fn deny_execute(mut self, deny_execute: bool) -> Self {
+ self.flags = set_bit(self.flags, 0x40, deny_execute);
+ self
+ }
+
+ pub fn is_auto(mut self, is_auto: bool) -> Self {
+ self.is_auto = is_auto;
+ self
+ }
+
+ pub(crate) fn create(self, view: &BinaryView) {
+ let ea_start = self.ea.start;
+ let ea_len = self.ea.end.wrapping_sub(ea_start);
+ let (b_start, b_len) = self.parent_backing.map_or((0, 0), |s| (s.start, s.end.wrapping_sub(s.start)));
+
+ unsafe {
+ if self.is_auto {
+ BNAddAutoSegment(view.handle, ea_start, ea_len, b_start, b_len, self.flags);
+ } else {
+ BNAddUserSegment(view.handle, ea_start, ea_len, b_start, b_len, self.flags);
+ }
+ }
+ }
+}
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct Segment {
+ handle: *mut BNSegment,
+}
+
+impl Segment {
+ pub(crate) unsafe fn from_raw(raw: *mut BNSegment) -> Self {
+ Self { handle: raw }
+ }
+
+ pub fn new(ea_range: Range<u64>) -> SegmentBuilder {
+ SegmentBuilder {
+ ea: ea_range,
+ parent_backing: None,
+ flags: 0,
+ is_auto: false,
+ }
+ }
+
+ pub fn address_range(&self) -> Range<u64> {
+ let start = unsafe { BNSegmentGetStart(self.handle) };
+ let end = unsafe { BNSegmentGetEnd(self.handle) };
+ start .. end
+ }
+
+ pub fn parent_backing(&self) -> Option<Range<u64>> {
+ let start = unsafe { BNSegmentGetDataOffset(self.handle) };
+ let end = unsafe { BNSegmentGetDataEnd(self.handle) };
+
+ if start != end {
+ Some(start .. end)
+ } else {
+ None
+ }
+ }
+
+ fn flags(&self) -> u32 {
+ unsafe { BNSegmentGetFlags(self.handle) }
+ }
+
+ pub fn executable(&self) -> bool {
+ self.flags() & 0x01 != 0
+ }
+
+ pub fn writable(&self) -> bool {
+ self.flags() & 0x02 != 0
+ }
+
+ pub fn readable(&self) -> bool {
+ self.flags() & 0x04 != 0
+ }
+
+ pub fn contains_data(&self) -> bool {
+ self.flags() & 0x08 != 0
+ }
+
+ pub fn contains_code(&self) -> bool {
+ self.flags() & 0x10 != 0
+ }
+
+ pub fn deny_write(&self) -> bool {
+ self.flags() & 0x20 != 0
+ }
+
+ pub fn deny_execute(&self) -> bool {
+ self.flags() & 0x40 != 0
+ }
+
+ pub fn auto_defined(&self) -> bool {
+ unsafe { BNSegmentIsAutoDefined(self.handle) }
+ }
+}
+
+impl ToOwned for Segment {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+unsafe impl RefCountable for Segment {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: BNNewSegmentReference(handle.handle),
+ })
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeSegment(handle.handle);
+ }
+}
+
+unsafe impl CoreOwnedArrayProvider for Segment {
+ type Raw = *mut BNSegment;
+ type Context = ();
+
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeSegmentList(raw, count);
+ }
+}
+
+unsafe impl<'a> CoreOwnedArrayWrapper<'a> for Segment {
+ type Wrapped = Guard<'a, Segment>;
+
+ unsafe fn wrap_raw(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped {
+ Guard::new(Segment::from_raw(*raw), context)
+ }
+}