diff options
| author | Ryan Snyder <ryan@vector35.com> | 2021-01-21 18:27:48 +0000 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2021-01-21 19:06:55 +0000 |
| commit | d3140edec185f47235b9e4642bdd56d6c585a341 (patch) | |
| tree | a61859c29e4e3539daea2b761bb1439d942beaf4 /rust/src/segment.rs | |
| parent | c0ddbf0c76d3f1bb7a2b2024f749afc8b9482575 (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.rs | 190 |
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) + } +} |
