lldb/
memoryregioninfo.rs

1use crate::{lldb_addr_t, sys, SBStream};
2use std::ffi::CStr;
3use std::fmt;
4
5/// Information about memory regions within a process.
6///
7/// See also:
8/// - [`SBProcess::get_memory_region_info()`](crate::SBProcess::get_memory_region_info)
9/// - [`SBProcess::get_memory_regions()`](crate::SBProcess::get_memory_regions)
10pub struct SBMemoryRegionInfo {
11    /// The underlying raw `SBMemoryRegionInfoRef`.
12    pub raw: sys::SBMemoryRegionInfoRef,
13}
14
15impl SBMemoryRegionInfo {
16    #[allow(missing_docs)]
17    pub(crate) fn new() -> Self {
18        SBMemoryRegionInfo::wrap(unsafe { sys::CreateSBMemoryRegionInfo() })
19    }
20
21    /// Construct a new `SBMemoryRegionInfo`.
22    pub(crate) fn wrap(raw: sys::SBMemoryRegionInfoRef) -> SBMemoryRegionInfo {
23        SBMemoryRegionInfo { raw }
24    }
25
26    #[allow(missing_docs)]
27    pub fn clear(&self) {
28        unsafe { sys::SBMemoryRegionInfoClear(self.raw) };
29    }
30
31    /// Get the base address of this memory range.
32    ///
33    /// See also:
34    ///
35    /// - [`SBMemoryRegionInfo::get_region_end()`]
36    pub fn get_region_base(&self) -> lldb_addr_t {
37        unsafe { sys::SBMemoryRegionInfoGetRegionBase(self.raw) }
38    }
39
40    /// Get the end address of this memory range.
41    ///
42    /// See also:
43    ///
44    /// - [`SBMemoryRegionInfo::get_region_base()`]
45    pub fn get_region_end(&self) -> lldb_addr_t {
46        unsafe { sys::SBMemoryRegionInfoGetRegionEnd(self.raw) }
47    }
48
49    /// Check if this memory address is marked readable to the process.
50    ///
51    /// See also:
52    ///
53    /// - [`SBMemoryRegionInfo::is_writable()`]
54    /// - [`SBMemoryRegionInfo::is_executable()`]
55    pub fn is_readable(&self) -> bool {
56        unsafe { sys::SBMemoryRegionInfoIsReadable(self.raw) }
57    }
58
59    /// Check if this memory address is marked writable to the process.
60    ///
61    /// See also:
62    ///
63    /// - [`SBMemoryRegionInfo::is_readable()`]
64    /// - [`SBMemoryRegionInfo::is_executable()`]
65    pub fn is_writable(&self) -> bool {
66        unsafe { sys::SBMemoryRegionInfoIsWritable(self.raw) }
67    }
68
69    /// Check if this memory address is marked executable to the process.
70    ///
71    /// See also:
72    ///
73    /// - [`SBMemoryRegionInfo::is_readable()`]
74    /// - [`SBMemoryRegionInfo::is_writable()`]
75    pub fn is_executable(&self) -> bool {
76        unsafe { sys::SBMemoryRegionInfoIsExecutable(self.raw) }
77    }
78
79    /// Check if this memory address is mapped into the process address
80    /// space.
81    pub fn is_mapped(&self) -> bool {
82        unsafe { sys::SBMemoryRegionInfoIsMapped(self.raw) }
83    }
84
85    /// Returns the name of the memory region mapped at the given
86    /// address.
87    ///
88    /// In case of memory mapped files it is the absolute path of
89    /// the file, otherwise it is a name associated with the memory
90    /// region. If no name can be determined, it returns `None`.
91    pub fn get_name(&self) -> Option<String> {
92        unsafe {
93            let ptr = sys::SBMemoryRegionInfoGetName(self.raw);
94
95            if !ptr.is_null() {
96                match CStr::from_ptr(ptr).to_str() {
97                    Ok(s) => Some(s.to_owned()),
98                    _ => panic!("No MemoryRegionInfo name string?"),
99                }
100            } else {
101                None
102            }
103        }
104    }
105
106    /// Returns whether this memory region has a list of memory pages
107    /// that have been modified -- that are dirty.
108    ///
109    /// The number of dirty pages may still be `0`.
110    ///
111    /// See also:
112    ///
113    /// - [`SBMemoryRegionInfo::dirty_pages()`]
114    pub fn has_dirty_memory_page_list(&self) -> bool {
115        unsafe { sys::SBMemoryRegionInfoHasDirtyMemoryPageList(self.raw) }
116    }
117
118    /// Returns an iterator over the addresses of modified pages in
119    /// this region.
120    ///
121    /// Check [`SBMemoryRegionInfo::has_dirty_memory_page_list()`] to
122    /// see if this information is available for this region.
123    pub fn dirty_pages(&self) -> SBMemoryRegionInfoDirtyPageIter {
124        SBMemoryRegionInfoDirtyPageIter { info: self, idx: 0 }
125    }
126
127    /// Returns the size of a memory page in this region
128    /// or `0` if this information is unavailable.
129    pub fn get_page_size(&self) -> i32 {
130        unsafe { sys::SBMemoryRegionInfoGetPageSize(self.raw) }
131    }
132}
133
134impl Clone for SBMemoryRegionInfo {
135    fn clone(&self) -> Self {
136        Self {
137            raw: unsafe { sys::CloneSBMemoryRegionInfo(self.raw) },
138        }
139    }
140}
141
142impl fmt::Debug for SBMemoryRegionInfo {
143    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
144        let stream = SBStream::new();
145        unsafe { sys::SBMemoryRegionInfoGetDescription(self.raw, stream.raw) };
146        write!(fmt, "SBMemoryRegionInfo {{ {} }}", stream.data())
147    }
148}
149
150impl Default for SBMemoryRegionInfo {
151    fn default() -> Self {
152        Self::new()
153    }
154}
155
156impl Drop for SBMemoryRegionInfo {
157    fn drop(&mut self) {
158        unsafe { sys::DisposeSBMemoryRegionInfo(self.raw) };
159    }
160}
161
162unsafe impl Send for SBMemoryRegionInfo {}
163unsafe impl Sync for SBMemoryRegionInfo {}
164
165/// Iterate over the addresses of dirty pages in a [memory region].
166///
167/// [memory region]: SBMemoryRegionInfo
168pub struct SBMemoryRegionInfoDirtyPageIter<'d> {
169    info: &'d SBMemoryRegionInfo,
170    idx: u32,
171}
172
173impl Iterator for SBMemoryRegionInfoDirtyPageIter<'_> {
174    type Item = lldb_addr_t;
175
176    fn next(&mut self) -> Option<Self::Item> {
177        if self.idx < unsafe { sys::SBMemoryRegionInfoGetNumDirtyPages(self.info.raw) } {
178            let r = Some(unsafe {
179                sys::SBMemoryRegionInfoGetDirtyPageAddressAtIndex(self.info.raw, self.idx)
180            });
181            self.idx += 1;
182            r
183        } else {
184            None
185        }
186    }
187
188    fn size_hint(&self) -> (usize, Option<usize>) {
189        let sz = unsafe { sys::SBMemoryRegionInfoGetNumDirtyPages(self.info.raw) } as usize;
190        (sz - self.idx as usize, Some(sz))
191    }
192}
193
194#[cfg(feature = "graphql")]
195#[juniper::graphql_object]
196impl SBMemoryRegionInfo {
197    // TODO(bm) This should be u64
198    fn region_base() -> i32 {
199        self.get_region_base() as i32
200    }
201
202    // TODO(bm) This should be u64
203    fn region_end() -> i32 {
204        self.get_region_end() as i32
205    }
206
207    fn is_readable() -> bool {
208        self.is_readable()
209    }
210
211    fn is_writable() -> bool {
212        self.is_writable()
213    }
214
215    fn is_executable() -> bool {
216        self.is_executable()
217    }
218
219    fn is_mapped() -> bool {
220        self.is_mapped()
221    }
222
223    fn name() -> Option<String> {
224        self.get_name()
225    }
226
227    fn page_size() -> i32 {
228        self.get_page_size()
229    }
230}