1use crate::binary_view::BinaryView;
2use crate::data_buffer::DataBuffer;
3use crate::file_accessor::{Accessor, FileAccessor};
4use crate::rc::Ref;
5use crate::segment::SegmentFlags;
6use crate::string::{raw_to_string, BnString, IntoCStr};
7use binaryninjacore_sys::*;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct MemoryRegionInfo {
16 pub name: String,
17 pub display_name: String,
18 pub start: u64,
19 pub length: u64,
20 pub flags: SegmentFlags,
21 pub enabled: bool,
22 pub rebaseable: bool,
23 pub fill: u8,
24 pub has_target: bool,
25 pub absolute_address_mode: bool,
26 pub local: bool,
27}
28
29impl MemoryRegionInfo {
30 pub fn end(&self) -> u64 {
31 self.start + self.length
32 }
33
34 fn from_raw(region: &BNMemoryRegionInfo) -> Self {
35 Self {
36 name: raw_to_string(region.name).unwrap_or_default(),
37 display_name: raw_to_string(region.displayName).unwrap_or_default(),
38 start: region.start,
39 length: region.length,
40 flags: SegmentFlags::from_raw(region.flags),
41 enabled: region.enabled,
42 rebaseable: region.rebaseable,
43 fill: region.fill,
44 has_target: region.hasTarget,
45 absolute_address_mode: region.absoluteAddressMode,
46 local: region.local,
47 }
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub struct ResolvedRange {
60 pub start: u64,
61 pub length: u64,
62 pub regions: Vec<MemoryRegionInfo>,
63}
64
65impl ResolvedRange {
66 pub fn end(&self) -> u64 {
67 self.start + self.length
68 }
69
70 pub fn active_region(&self) -> Option<&MemoryRegionInfo> {
72 self.regions.first()
73 }
74
75 pub fn name(&self) -> Option<&str> {
77 self.active_region().map(|r| r.name.as_str())
78 }
79
80 pub fn flags(&self) -> SegmentFlags {
82 self.active_region()
83 .map(|r| r.flags)
84 .unwrap_or(SegmentFlags::from_raw(0))
85 }
86}
87
88#[derive(PartialEq, Eq, Hash)]
124pub struct MemoryMap {
125 view: Ref<BinaryView>,
126}
127
128impl MemoryMap {
129 pub fn new(view: Ref<BinaryView>) -> Self {
130 Self { view }
131 }
132
133 pub fn regions(&self) -> Vec<MemoryRegionInfo> {
135 let mut count: usize = 0;
136 let regions_raw = unsafe { BNGetMemoryRegions(self.view.handle, &mut count) };
137 if regions_raw.is_null() {
138 return Vec::new();
139 }
140 let mut result = Vec::with_capacity(count);
141 for i in 0..count {
142 let region = unsafe { &*regions_raw.add(i) };
143 result.push(MemoryRegionInfo::from_raw(region));
144 }
145 unsafe { BNFreeMemoryRegions(regions_raw, count) };
146 result
147 }
148
149 pub fn ranges(&self) -> Vec<ResolvedRange> {
154 let mut count: usize = 0;
155 let ranges_raw = unsafe { BNGetResolvedMemoryRanges(self.view.handle, &mut count) };
156 if ranges_raw.is_null() {
157 return Vec::new();
158 }
159 let mut result = Vec::with_capacity(count);
160 for i in 0..count {
161 let range = unsafe { &*ranges_raw.add(i) };
162 let mut regions = Vec::with_capacity(range.regionCount);
163 for j in 0..range.regionCount {
164 let region = unsafe { &*range.regions.add(j) };
165 regions.push(MemoryRegionInfo::from_raw(region));
166 }
167 result.push(ResolvedRange {
168 start: range.start,
169 length: range.length,
170 regions,
171 });
172 }
173 unsafe { BNFreeResolvedMemoryRanges(ranges_raw, count) };
174 result
175 }
176
177 pub fn get_region(&self, name: &str) -> Option<MemoryRegionInfo> {
182 let name_raw = name.to_cstr();
183 let mut result: BNMemoryRegionInfo = unsafe { std::mem::zeroed() };
184 let found =
185 unsafe { BNGetMemoryRegionInfo(self.view.handle, name_raw.as_ptr(), &mut result) };
186 if !found {
187 return None;
188 }
189 let info = MemoryRegionInfo::from_raw(&result);
190 unsafe { BNFreeMemoryRegionInfo(&mut result) };
191 Some(info)
192 }
193
194 pub fn get_active_region_at(&self, addr: u64) -> Option<MemoryRegionInfo> {
197 let mut result: BNMemoryRegionInfo = unsafe { std::mem::zeroed() };
198 let found = unsafe { BNGetActiveMemoryRegionInfoAt(self.view.handle, addr, &mut result) };
199 if !found {
200 return None;
201 }
202 let info = MemoryRegionInfo::from_raw(&result);
203 unsafe { BNFreeMemoryRegionInfo(&mut result) };
204 Some(info)
205 }
206
207 pub fn get_resolved_range_at(&self, addr: u64) -> Option<ResolvedRange> {
210 let mut result: BNResolvedMemoryRange = unsafe { std::mem::zeroed() };
211 let found = unsafe { BNGetResolvedMemoryRangeAt(self.view.handle, addr, &mut result) };
212 if !found {
213 return None;
214 }
215 let mut regions = Vec::with_capacity(result.regionCount);
216 for j in 0..result.regionCount {
217 let region = unsafe { &*result.regions.add(j) };
218 regions.push(MemoryRegionInfo::from_raw(region));
219 }
220 let resolved = ResolvedRange {
221 start: result.start,
222 length: result.length,
223 regions,
224 };
225 unsafe { BNFreeResolvedMemoryRange(&mut result) };
226 Some(resolved)
227 }
228
229 pub fn base_description(&self) -> String {
231 let desc_raw = unsafe { BNGetBaseMemoryMapDescription(self.view.handle) };
232 unsafe { BnString::into_string(desc_raw) }
233 }
234
235 pub fn description(&self) -> String {
237 let desc_raw = unsafe { BNGetMemoryMapDescription(self.view.handle) };
238 unsafe { BnString::into_string(desc_raw) }
239 }
240
241 pub fn set_logical_enabled(&mut self, enabled: bool) {
248 unsafe { BNSetLogicalMemoryMapEnabled(self.view.handle, enabled) };
249 }
250
251 pub fn is_activated(&self) -> bool {
265 unsafe { BNIsMemoryMapActivated(self.view.handle) }
266 }
267
268 pub fn add_binary_memory_region(
269 &mut self,
270 name: &str,
271 start: u64,
272 view: &BinaryView,
273 segment_flags: Option<SegmentFlags>,
274 ) -> bool {
275 let name_raw = name.to_cstr();
276 unsafe {
277 BNAddBinaryMemoryRegion(
278 self.view.handle,
279 name_raw.as_ptr(),
280 start,
281 view.handle,
282 segment_flags.unwrap_or_default().into_raw(),
283 )
284 }
285 }
286
287 pub fn add_data_memory_region(
291 &mut self,
292 name: &str,
293 start: u64,
294 data: &DataBuffer,
295 segment_flags: Option<SegmentFlags>,
296 ) -> bool {
297 let name_raw = name.to_cstr();
298 unsafe {
299 BNAddDataMemoryRegion(
300 self.view.handle,
301 name_raw.as_ptr(),
302 start,
303 data.as_raw(),
304 segment_flags.unwrap_or_default().into_raw(),
305 )
306 }
307 }
308
309 pub fn add_remote_memory_region<A: Accessor>(
319 &mut self,
320 name: &str,
321 start: u64,
322 accessor: &mut FileAccessor<A>,
323 segment_flags: Option<SegmentFlags>,
324 ) -> bool {
325 let name_raw = name.to_cstr();
326 unsafe {
327 BNAddRemoteMemoryRegion(
328 self.view.handle,
329 name_raw.as_ptr(),
330 start,
331 &mut accessor.raw,
332 segment_flags.unwrap_or_default().into_raw(),
333 )
334 }
335 }
336
337 pub fn add_unbacked_memory_region(
339 &mut self,
340 name: &str,
341 start: u64,
342 length: u64,
343 segment_flags: Option<SegmentFlags>,
344 fill: Option<u8>,
345 ) -> bool {
346 let name_raw = name.to_cstr();
347 unsafe {
348 BNAddUnbackedMemoryRegion(
349 self.view.handle,
350 name_raw.as_ptr(),
351 start,
352 length,
353 segment_flags.unwrap_or_default().into_raw(),
354 fill.unwrap_or_default(),
355 )
356 }
357 }
358
359 pub fn remove_memory_region(&mut self, name: &str) -> bool {
360 let name_raw = name.to_cstr();
361 unsafe { BNRemoveMemoryRegion(self.view.handle, name_raw.as_ptr()) }
362 }
363
364 pub fn active_memory_region_at(&self, addr: u64) -> String {
367 unsafe {
368 let name_raw = BNGetActiveMemoryRegionAt(self.view.handle, addr);
369 BnString::into_string(name_raw)
370 }
371 }
372
373 pub fn memory_region_flags(&self, name: &str) -> SegmentFlags {
374 let name_raw = name.to_cstr();
375 let flags_raw = unsafe { BNGetMemoryRegionFlags(self.view.handle, name_raw.as_ptr()) };
376 SegmentFlags::from_raw(flags_raw)
377 }
378
379 pub fn set_memory_region_flags(&mut self, name: &str, flags: SegmentFlags) -> bool {
380 let name_raw = name.to_cstr();
381 unsafe { BNSetMemoryRegionFlags(self.view.handle, name_raw.as_ptr(), flags.into_raw()) }
382 }
383
384 pub fn is_memory_region_enabled(&self, name: &str) -> bool {
385 let name_raw = name.to_cstr();
386 unsafe { BNIsMemoryRegionEnabled(self.view.handle, name_raw.as_ptr()) }
387 }
388
389 pub fn set_memory_region_enabled(&mut self, name: &str, enabled: bool) -> bool {
390 let name_raw = name.to_cstr();
391 unsafe { BNSetMemoryRegionEnabled(self.view.handle, name_raw.as_ptr(), enabled) }
392 }
393
394 pub fn is_memory_region_rebaseable(&self, name: &str) -> bool {
396 let name_raw = name.to_cstr();
397 unsafe { BNIsMemoryRegionRebaseable(self.view.handle, name_raw.as_ptr()) }
398 }
399
400 pub fn set_memory_region_rebaseable(&mut self, name: &str, enabled: bool) -> bool {
401 let name_raw = name.to_cstr();
402 unsafe { BNSetMemoryRegionRebaseable(self.view.handle, name_raw.as_ptr(), enabled) }
403 }
404
405 pub fn memory_region_fill(&self, name: &str) -> u8 {
406 let name_raw = name.to_cstr();
407 unsafe { BNGetMemoryRegionFill(self.view.handle, name_raw.as_ptr()) }
408 }
409
410 pub fn set_memory_region_fill(&mut self, name: &str, fill: u8) -> bool {
411 let name_raw = name.to_cstr();
412 unsafe { BNSetMemoryRegionFill(self.view.handle, name_raw.as_ptr(), fill) }
413 }
414
415 pub fn reset(&mut self) {
416 unsafe { BNResetMemoryMap(self.view.handle) }
417 }
418}