perf_event_data/records/
comm.rs

1use std::borrow::Cow;
2use std::ffi::OsStr;
3use std::fmt;
4
5use crate::prelude::*;
6
7used_in_docs!(OsStr);
8
9/// COMM records indicate changes in process names.
10///
11/// There are multiple ways that this could happen: [`execve(2)`],
12/// [`prctl(PR_SET_NAME)`], as well as writing to `/proc/self/comm`.
13///
14/// Since Linux 3.10 the kernel will set the `COMM_EXEC` bit in the misc flags
15/// if the record is due to an [`execve(2)`] syscall. You can set `comm_exec`
16/// when building to detect whether this is supported.
17///
18/// This struct corresponds to `PERF_RECORD_COMM`. See the [manpage] for more
19/// documentation.
20///
21/// [`execve(2)`]: https://man7.org/linux/man-pages/man2/execve.2.html
22/// [`prctl(PR_SET_NAME)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
23/// [`COMM_EXEC`]: MiscFlags::COMM_EXEC
24/// [manpage]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
25#[derive(Clone)]
26pub struct Comm<'a> {
27    /// The process ID.
28    pub pid: u32,
29
30    /// The thread ID.
31    pub tid: u32,
32
33    /// The new name of the process.
34    ///
35    /// If on unix systems you can use `comm_os` to get this as an [`OsStr`].
36    pub comm: Cow<'a, [u8]>,
37}
38
39impl<'a> Comm<'a> {
40    /// The new name of the process, as an [`OsStr`].
41    #[cfg(unix)]
42    pub fn comm_os(&self) -> &OsStr {
43        use std::os::unix::ffi::OsStrExt;
44
45        OsStrExt::from_bytes(&self.comm)
46    }
47
48    /// Convert all the borrowed data in this `Comm` into owned data.
49    pub fn into_owned(self) -> Comm<'static> {
50        Comm {
51            comm: self.comm.into_owned().into(),
52            ..self
53        }
54    }
55}
56
57impl<'p> Parse<'p> for Comm<'p> {
58    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
59    where
60        E: Endian,
61        B: ParseBuf<'p>,
62    {
63        Ok(Self {
64            pid: p.parse()?,
65            tid: p.parse()?,
66            comm: p.parse_rest_trim_nul()?,
67        })
68    }
69}
70
71impl fmt::Debug for Comm<'_> {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        f.debug_struct("Comm")
74            .field("pid", &self.pid)
75            .field("tid", &self.tid)
76            .field("comm", &crate::util::fmt::ByteStr(&self.comm))
77            .finish()
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84    use crate::endian::Little;
85
86    #[test]
87    fn test_parse() {
88        #[rustfmt::skip]
89        let bytes: &[u8] = &[
90            0x10, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
91            b't', b'e', b's', b't', 0x00, 0x00, 0x00, 0x00
92        ];
93
94        let mut parser: Parser<_, Little> = Parser::new(bytes, ParseConfig::default());
95        let comm: Comm = parser.parse().unwrap();
96
97        assert_eq!(comm.pid, 0x1010);
98        assert_eq!(comm.tid, 0x0500);
99        assert_eq!(&*comm.comm, b"test");
100    }
101}