perf_event_data/records/
mmap.rs

1use std::borrow::Cow;
2use std::ffi::OsStr;
3use std::fmt;
4
5use crate::prelude::*;
6use crate::Mmap2;
7
8/// MMAP events record memory mappings.
9///
10/// This struct corresponds to `PERF_RECORD_MMAP`. See the [manpage] for more
11/// documentation here.
12///
13/// [manpage]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
14#[derive(Clone)]
15pub struct Mmap<'a> {
16    /// The process ID.
17    pub pid: u32,
18
19    /// The thread ID.
20    pub tid: u32,
21
22    /// The address that the mapping was placed at in the process' address
23    /// space.
24    pub addr: u64,
25
26    /// The length, in bytes, of the allocated memory.
27    pub len: u64,
28
29    /// The page offset of the memory mapping.
30    pub pgoff: u64,
31
32    /// The path to the file that is being mapped, if there is one.
33    ///
34    /// # Notes
35    /// - Not all memory mappings have a path on the file system. In cases where
36    ///   there is no such path then this will be a label(ish) string from the
37    ///   kernel (e.g. `[stack]`, `[heap]`, `[vdso]`, etc.)
38    /// - Just because the mapping has a path doesn't necessarily mean that the
39    ///   file at that path was the file that was mapped. The file may have been
40    ///   deleted in the meantime or the process may be under a chroot.
41    ///
42    /// If you need to be able to tell whether the file at the path is the same
43    /// one as was mapped you will need to use [`Mmap2`] instead.
44    pub filename: Cow<'a, [u8]>,
45}
46
47impl<'a> Mmap<'a> {
48    /// The path to the file that is being mapped, as an [`OsStr`].
49    ///
50    /// # Notes
51    /// - Not all memory mappings have a path on the file system. In cases where
52    ///   there is no such path then this will be a label(ish) string from the
53    ///   kernel (e.g. `[stack]`, `[heap]`, `[vdso]`, etc.)
54    /// - Just because the mapping has a path doesn't necessarily mean that the
55    ///   file at that path was the file that was mapped. The file may have been
56    ///   deleted in the meantime or the process may be under a chroot.
57    ///
58    /// If you need to be able to tell whether the file at the path is the same
59    /// one as was mapped you will need to use [`Mmap2`] instead.
60    #[cfg(unix)]
61    pub fn filename_os(&self) -> &OsStr {
62        use std::os::unix::ffi::OsStrExt;
63
64        OsStrExt::from_bytes(&self.filename)
65    }
66
67    /// Convert all the borrowed data in this `Mmap` into owned data.
68    pub fn into_owned(self) -> Mmap<'static> {
69        Mmap {
70            filename: self.filename.into_owned().into(),
71            ..self
72        }
73    }
74}
75
76impl<'p> Parse<'p> for Mmap<'p> {
77    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
78    where
79        E: Endian,
80        B: ParseBuf<'p>,
81    {
82        Ok(Self {
83            pid: p.parse()?,
84            tid: p.parse()?,
85            addr: p.parse()?,
86            len: p.parse()?,
87            pgoff: p.parse()?,
88            filename: p.parse_rest_trim_nul()?,
89        })
90    }
91}
92
93impl<'a> From<Mmap2<'a>> for Mmap<'a> {
94    fn from(value: Mmap2<'a>) -> Self {
95        value.into_mmap()
96    }
97}
98
99impl fmt::Debug for Mmap<'_> {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        f.debug_struct("Mmap")
102            .field("pid", &self.pid)
103            .field("tid", &self.tid)
104            .field("addr", &crate::util::fmt::HexAddr(self.addr))
105            .field("len", &self.len)
106            .field("pgoff", &self.pgoff)
107            .field("filename", &crate::util::fmt::ByteStr(&self.filename))
108            .finish()
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use crate::endian::Little;
115
116    use super::*;
117
118    #[test]
119    fn test_parse() {
120        let bytes: &[u8] = &[
121            10, 100, 0, 0, 11, 100, 0, 0, 0, 160, 118, 129, 189, 127, 0, 0, 0, 16, 0, 0, 0, 0, 0,
122            0, 0, 160, 118, 129, 189, 127, 0, 0, 47, 47, 97, 110, 111, 110, 0, 0,
123        ];
124
125        let mut parser: Parser<_, Little> = Parser::new(bytes, ParseConfig::default());
126        let mmap: Mmap = parser.parse().unwrap();
127
128        assert_eq!(mmap.pid, 25610);
129        assert_eq!(mmap.tid, 25611);
130        assert_eq!(mmap.addr, 0x7FBD8176A000);
131        assert_eq!(mmap.len, 4096);
132        assert_eq!(mmap.pgoff, 0x7FBD8176A000);
133        assert_eq!(&*mmap.filename, b"//anon");
134    }
135}