Skip to content

Commit 48f9c54

Browse files
committed
Implement Rust MemoryMap
Also split out SegmentFlags and fix some UB with the section creation
1 parent e4b71a2 commit 48f9c54

File tree

5 files changed

+373
-100
lines changed

5 files changed

+373
-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: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
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+
// TODO: `segment_flags` should be typed.
45+
pub fn add_binary_memory_region(
46+
&mut self,
47+
name: impl BnStrCompatible,
48+
start: u64,
49+
view: &BinaryView,
50+
segment_flags: Option<SegmentFlags>,
51+
) -> bool {
52+
let name_raw = name.into_bytes_with_nul();
53+
unsafe {
54+
BNAddBinaryMemoryRegion(
55+
self.view.handle,
56+
name_raw.as_ref().as_ptr() as *const c_char,
57+
start,
58+
view.handle,
59+
segment_flags.unwrap_or_default().into_raw(),
60+
)
61+
}
62+
}
63+
64+
pub fn add_data_memory_region(
65+
&mut self,
66+
name: impl BnStrCompatible,
67+
start: u64,
68+
data: &DataBuffer,
69+
segment_flags: Option<SegmentFlags>,
70+
) -> bool {
71+
let name_raw = name.into_bytes_with_nul();
72+
unsafe {
73+
BNAddDataMemoryRegion(
74+
self.view.handle,
75+
name_raw.as_ref().as_ptr() as *const c_char,
76+
start,
77+
data.as_raw(),
78+
segment_flags.unwrap_or_default().into_raw(),
79+
)
80+
}
81+
}
82+
83+
pub fn add_remote_memory_region(
84+
&mut self,
85+
name: impl BnStrCompatible,
86+
start: u64,
87+
accessor: &mut FileAccessor,
88+
segment_flags: Option<SegmentFlags>,
89+
) -> bool {
90+
let name_raw = name.into_bytes_with_nul();
91+
unsafe {
92+
BNAddRemoteMemoryRegion(
93+
self.view.handle,
94+
name_raw.as_ref().as_ptr() as *const c_char,
95+
start,
96+
&mut accessor.api_object,
97+
segment_flags.unwrap_or_default().into_raw(),
98+
)
99+
}
100+
}
101+
102+
pub fn remove_memory_region(&mut self, name: impl BnStrCompatible) -> bool {
103+
let name_raw = name.into_bytes_with_nul();
104+
unsafe {
105+
BNRemoveMemoryRegion(
106+
self.view.handle,
107+
name_raw.as_ref().as_ptr() as *const c_char,
108+
)
109+
}
110+
}
111+
112+
pub fn active_memory_region_at(&self, addr: u64) -> BnString {
113+
unsafe {
114+
let name_raw = BNGetActiveMemoryRegionAt(self.view.handle, addr);
115+
BnString::from_raw(name_raw)
116+
}
117+
}
118+
119+
pub fn memory_region_flags(&self, name: impl BnStrCompatible) -> SegmentFlags {
120+
let name_raw = name.into_bytes_with_nul();
121+
let flags_raw = unsafe {
122+
BNGetMemoryRegionFlags(
123+
self.view.handle,
124+
name_raw.as_ref().as_ptr() as *const c_char,
125+
)
126+
};
127+
SegmentFlags::from_raw(flags_raw)
128+
}
129+
130+
pub fn set_memory_region_flags(
131+
&mut self,
132+
name: impl BnStrCompatible,
133+
flags: SegmentFlags,
134+
) -> bool {
135+
let name_raw = name.into_bytes_with_nul();
136+
unsafe {
137+
BNSetMemoryRegionFlags(
138+
self.view.handle,
139+
name_raw.as_ref().as_ptr() as *const c_char,
140+
flags.into_raw(),
141+
)
142+
}
143+
}
144+
145+
pub fn is_memory_region_enabled(&self, name: impl BnStrCompatible) -> bool {
146+
let name_raw = name.into_bytes_with_nul();
147+
unsafe {
148+
BNIsMemoryRegionEnabled(
149+
self.view.handle,
150+
name_raw.as_ref().as_ptr() as *const c_char,
151+
)
152+
}
153+
}
154+
155+
pub fn set_memory_region_enabled(&mut self, name: impl BnStrCompatible, enabled: bool) -> bool {
156+
let name_raw = name.into_bytes_with_nul();
157+
unsafe {
158+
BNSetMemoryRegionEnabled(
159+
self.view.handle,
160+
name_raw.as_ref().as_ptr() as *const c_char,
161+
enabled,
162+
)
163+
}
164+
}
165+
166+
// TODO: Should we just call this is_memory_region_relocatable?
167+
pub fn is_memory_region_rebaseable(&self, name: impl BnStrCompatible) -> bool {
168+
let name_raw = name.into_bytes_with_nul();
169+
unsafe {
170+
BNIsMemoryRegionRebaseable(
171+
self.view.handle,
172+
name_raw.as_ref().as_ptr() as *const c_char,
173+
)
174+
}
175+
}
176+
177+
pub fn set_memory_region_rebaseable(
178+
&mut self,
179+
name: impl BnStrCompatible,
180+
enabled: bool,
181+
) -> bool {
182+
let name_raw = name.into_bytes_with_nul();
183+
unsafe {
184+
BNSetMemoryRegionRebaseable(
185+
self.view.handle,
186+
name_raw.as_ref().as_ptr() as *const c_char,
187+
enabled,
188+
)
189+
}
190+
}
191+
192+
pub fn memory_region_fill(&self, name: impl BnStrCompatible) -> u8 {
193+
let name_raw = name.into_bytes_with_nul();
194+
unsafe {
195+
BNGetMemoryRegionFill(
196+
self.view.handle,
197+
name_raw.as_ref().as_ptr() as *const c_char,
198+
)
199+
}
200+
}
201+
202+
pub fn set_memory_region_fill(&mut self, name: impl BnStrCompatible, fill: u8) -> bool {
203+
let name_raw = name.into_bytes_with_nul();
204+
unsafe {
205+
BNSetMemoryRegionFill(
206+
self.view.handle,
207+
name_raw.as_ref().as_ptr() as *const c_char,
208+
fill,
209+
)
210+
}
211+
}
212+
213+
pub fn reset(&mut self) {
214+
unsafe { BNResetMemoryMap(self.view.handle) }
215+
}
216+
}

0 commit comments

Comments
 (0)