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