in reverie-ptrace/src/validation.rs [193:262]
fn start_counter(
tid: libc::pid_t,
group_fd: libc::c_int,
attr: &mut perf::perf_event_attr,
mut disabled_txcp: Option<&mut bool>,
) -> Result<ScopedFd, PmuValidationError> {
attr.set_pinned((group_fd == -1) as u64);
if let Some(disabled) = disabled_txcp.as_mut() {
**disabled = false
}
let fd_result = Errno::result(unsafe {
libc::syscall(
libc::SYS_perf_event_open,
attr as *mut perf::perf_event_attr,
tid,
-1,
group_fd,
perf::PERF_FLAG_FD_CLOEXEC,
)
});
match &fd_result {
Err(Errno::EINVAL) if attr.config & IN_TXCP > 0 => {
// The kernel might not support IN_TXCP, so try again without it.
let mut tmp_attr = *attr;
tmp_attr.config &= !IN_TXCP;
let no_txcp_fd = Errno::result(unsafe {
libc::syscall(
libc::SYS_perf_event_open,
&tmp_attr,
tid,
-1,
group_fd,
perf::PERF_FLAG_FD_CLOEXEC,
)
});
if no_txcp_fd.is_ok() {
if let Some(disabled) = disabled_txcp.as_mut() {
**disabled = true
}
warn!("kernel does not support IN_TXCP");
}
no_txcp_fd
}
_ => fd_result,
}
.map(|raw_fd| raw_fd.into())
.map_err(|errno| match errno {
Errno::EACCES => PmuValidationError::CouldNotCreateTimer {
errno,
msg: "Permission denied to use 'perf_event_open'; are hardware perf events \
available? See https://github.com/rr-debugger/rr/wiki/Will-rr-work-on-my-system",
},
Errno::ENOENT => PmuValidationError::CouldNotCreateTimer {
errno,
msg: "Unable to open performance counter with 'perf_event_open'; \
are hardware perf events available? See \
https://github.com/rr-debugger/rr/wiki/Will-rr-work-on-my-system",
},
_ => PmuValidationError::CouldNotCreateTimer {
errno,
msg: "See - https://man7.org/linux/man-pages/man3/errno.3.html",
},
})
}