Skip to content

Commit a87f488

Browse files
committed
Implement Rust MemoryMap
Also split out SegmentFlags and fix some UB with the section creation
1 parent 57d04f2 commit a87f488

File tree

5 files changed

+372
-100
lines changed

5 files changed

+372
-100
lines changed

rust/src/binary_view.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use binaryninjacore_sys::*;
2626
use crate::architecture::{Architecture, CoreArchitecture};
2727
use crate::base_detection::BaseAddressDetection;
2828
use crate::basic_block::BasicBlock;
29+
use crate::binary_view::memory_map::MemoryMap;
2930
use crate::component::{Component, IntoComponentGuid};
3031
use crate::confidence::Conf;
3132
use crate::data_buffer::DataBuffer;
@@ -64,6 +65,8 @@ use std::ptr::NonNull;
6465
use std::{result, slice};
6566
// TODO : general reorg of modules related to bv
6667

68+
pub mod memory_map;
69+
6770
pub type Result<R> = result::Result<R, ()>;
6871
pub type BinaryViewEventType = BNBinaryViewEventType;
6972
pub type AnalysisState = BNAnalysisState;
@@ -870,7 +873,7 @@ pub trait BinaryViewExt: BinaryViewBase {
870873
unsafe { BNCancelBulkAddSegments(self.as_ref().handle) }
871874
}
872875

873-
fn add_section<S: BnStrCompatible>(&self, section: SectionBuilder<S>) {
876+
fn add_section(&self, section: SectionBuilder) {
874877
section.create(self.as_ref());
875878
}
876879

@@ -918,6 +921,10 @@ pub trait BinaryViewExt: BinaryViewBase {
918921
}
919922
}
920923

924+
fn memory_map(&self) -> MemoryMap {
925+
MemoryMap::new(self.as_ref().to_owned())
926+
}
927+
921928
fn add_auto_function(&self, plat: &Platform, addr: u64) -> Option<Ref<Function>> {
922929
unsafe {
923930
let handle = BNAddFunctionForAnalysis(

rust/src/binary_view/memory_map.rs

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
use crate::binary_view::BinaryView;
2+
use crate::data_buffer::DataBuffer;
3+
use crate::file_accessor::FileAccessor;
4+
use crate::rc::Ref;
5+
use crate::segment::SegmentFlags;
6+
use crate::string::{BnStrCompatible, BnString};
7+
use binaryninjacore_sys::*;
8+
use std::ffi::c_char;
9+
10+
#[derive(PartialEq, Eq, Hash)]
11+
pub struct MemoryMap {
12+
view: Ref<BinaryView>,
13+
}
14+
15+
impl MemoryMap {
16+
pub fn new(view: Ref<BinaryView>) -> Self {
17+
Self { view }
18+
}
19+
20+
// TODO: There does not seem to be a way to enumerate memory regions.
21+
22+
/// JSON string representation of the base [`MemoryMap`], consisting of unresolved auto and user segments.
23+
pub fn base_description(&self) -> String {
24+
let desc_raw = unsafe { BNGetBaseMemoryMapDescription(self.view.handle) };
25+
unsafe { BnString::from_raw(desc_raw) }.to_string()
26+
}
27+
28+
/// JSON string representation of the [`MemoryMap`].
29+
pub fn description(&self) -> String {
30+
let desc_raw = unsafe { BNGetMemoryMapDescription(self.view.handle) };
31+
unsafe { BnString::from_raw(desc_raw) }.to_string()
32+
}
33+
34+
// When enabled, the memory map will present a simplified, logical view that merges and abstracts virtual memory
35+
// regions based on criteria such as contiguity and flag consistency. This view is designed to provide a higher-level
36+
// representation for user analysis, hiding underlying mapping details.
37+
//
38+
// When disabled, the memory map will revert to displaying the virtual view, which corresponds directly to the individual
39+
// segments mapped from the raw file without any merging or abstraction.
40+
pub fn set_logical_enabled(&mut self, enabled: bool) {
41+
unsafe { BNSetLogicalMemoryMapEnabled(self.view.handle, enabled) };
42+
}
43+
44+
pub fn add_binary_memory_region(
45+
&mut self,
46+
name: impl BnStrCompatible,
47+
start: u64,
48+
view: &BinaryView,
49+
segment_flags: Option<SegmentFlags>,
50+
) -> bool {
51+
let name_raw = name.into_bytes_with_nul();
52+
unsafe {
53+
BNAddBinaryMemoryRegion(
54+
self.view.handle,
55+
name_raw.as_ref().as_ptr() as *const c_char,
56+
start,
57+
view.handle,
58+
segment_flags.unwrap_or_default().into_raw(),
59+
)
60+
}
61+
}
62+
63+
pub fn add_data_memory_region(
64+
&mut self,
65+
name: impl BnStrCompatible,
66+
start: u64,
67+
data: &DataBuffer,
68+
segment_flags: Option<SegmentFlags>,
69+
) -> bool {
70+
let name_raw = name.into_bytes_with_nul();
71+
unsafe {
72+
BNAddDataMemoryRegion(
73+
self.view.handle,
74+
name_raw.as_ref().as_ptr() as *const c_char,
75+
start,
76+
data.as_raw(),
77+
segment_flags.unwrap_or_default().into_raw(),
78+
)
79+
}
80+
}
81+
82+
pub fn add_remote_memory_region(
83+
&mut self,
84+
name: impl BnStrCompatible,
85+
start: u64,
86+
accessor: &mut FileAccessor,
87+
segment_flags: Option<SegmentFlags>,
88+
) -> bool {
89+
let name_raw = name.into_bytes_with_nul();
90+
unsafe {
91+
BNAddRemoteMemoryRegion(
92+
self.view.handle,
93+
name_raw.as_ref().as_ptr() as *const c_char,
94+
start,
95+
&mut accessor.api_object,
96+
segment_flags.unwrap_or_default().into_raw(),
97+
)
98+
}
99+
}
100+
101+
pub fn remove_memory_region(&mut self, name: impl BnStrCompatible) -> bool {
102+
let name_raw = name.into_bytes_with_nul();
103+
unsafe {
104+
BNRemoveMemoryRegion(
105+
self.view.handle,
106+
name_raw.as_ref().as_ptr() as *const c_char,
107+
)
108+
}
109+
}
110+
111+
pub fn active_memory_region_at(&self, addr: u64) -> BnString {
112+
unsafe {
113+
let name_raw = BNGetActiveMemoryRegionAt(self.view.handle, addr);
114+
BnString::from_raw(name_raw)
115+
}
116+
}
117+
118+
pub fn memory_region_flags(&self, name: impl BnStrCompatible) -> SegmentFlags {
119+
let name_raw = name.into_bytes_with_nul();
120+
let flags_raw = unsafe {
121+
BNGetMemoryRegionFlags(
122+
self.view.handle,
123+
name_raw.as_ref().as_ptr() as *const c_char,
124+
)
125+
};
126+
SegmentFlags::from_raw(flags_raw)
127+
}
128+
129+
pub fn set_memory_region_flags(
130+
&mut self,
131+
name: impl BnStrCompatible,
132+
flags: SegmentFlags,
133+
) -> bool {
134+
let name_raw = name.into_bytes_with_nul();
135+
unsafe {
136+
BNSetMemoryRegionFlags(
137+
self.view.handle,
138+
name_raw.as_ref().as_ptr() as *const c_char,
139+
flags.into_raw(),
140+
)
141+
}
142+
}
143+
144+
pub fn is_memory_region_enabled(&self, name: impl BnStrCompatible) -> bool {
145+
let name_raw = name.into_bytes_with_nul();
146+
unsafe {
147+
BNIsMemoryRegionEnabled(
148+
self.view.handle,
149+
name_raw.as_ref().as_ptr() as *const c_char,
150+
)
151+
}
152+
}
153+
154+
pub fn set_memory_region_enabled(&mut self, name: impl BnStrCompatible, enabled: bool) -> bool {
155+
let name_raw = name.into_bytes_with_nul();
156+
unsafe {
157+
BNSetMemoryRegionEnabled(
158+
self.view.handle,
159+
name_raw.as_ref().as_ptr() as *const c_char,
160+
enabled,
161+
)
162+
}
163+
}
164+
165+
// TODO: Should we just call this is_memory_region_relocatable?
166+
pub fn is_memory_region_rebaseable(&self, name: impl BnStrCompatible) -> bool {
167+
let name_raw = name.into_bytes_with_nul();
168+
unsafe {
169+
BNIsMemoryRegionRebaseable(
170+
self.view.handle,
171+
name_raw.as_ref().as_ptr() as *const c_char,
172+
)
173+
}
174+
}
175+
176+
pub fn set_memory_region_rebaseable(
177+
&mut self,
178+
name: impl BnStrCompatible,
179+
enabled: bool,
180+
) -> bool {
181+
let name_raw = name.into_bytes_with_nul();
182+
unsafe {
183+
BNSetMemoryRegionRebaseable(
184+
self.view.handle,
185+
name_raw.as_ref().as_ptr() as *const c_char,
186+
enabled,
187+
)
188+
}
189+
}
190+
191+
pub fn memory_region_fill(&self, name: impl BnStrCompatible) -> u8 {
192+
let name_raw = name.into_bytes_with_nul();
193+
unsafe {
194+
BNGetMemoryRegionFill(
195+
self.view.handle,
196+
name_raw.as_ref().as_ptr() as *const c_char,
197+
)
198+
}
199+
}
200+
201+
pub fn set_memory_region_fill(&mut self, name: impl BnStrCompatible, fill: u8) -> bool {
202+
let name_raw = name.into_bytes_with_nul();
203+
unsafe {
204+
BNSetMemoryRegionFill(
205+
self.view.handle,
206+
name_raw.as_ref().as_ptr() as *const c_char,
207+
fill,
208+
)
209+
}
210+
}
211+
212+
pub fn reset(&mut self) {
213+
unsafe { BNResetMemoryMap(self.view.handle) }
214+
}
215+
}

0 commit comments

Comments
 (0)