feat: get_tracefs function

pull/471/head
banditopazzo 2 years ago
parent 556463a85f
commit c6c4ac7eea

@ -206,6 +206,10 @@ pub enum ProgramError {
/// program name /// program name
name: String, name: String,
}, },
/// TraceFS not found.
#[error("tracefs non found")]
TraceFsNotFound,
} }
/// A [`Program`] file descriptor. /// A [`Program`] file descriptor.

@ -2,14 +2,15 @@ use libc::pid_t;
use std::{ use std::{
fs::{self, OpenOptions}, fs::{self, OpenOptions},
io::{self, Write}, io::{self, Write},
path::Path,
process, process,
}; };
use crate::{ use crate::{
programs::{ programs::{
kprobe::KProbeError, perf_attach, perf_attach::PerfLink, perf_attach_debugfs, kprobe::KProbeError, perf_attach, perf_attach::PerfLink, perf_attach_debugfs,
trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, Link, ProgramData, trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, utils::get_tracefs, Link,
ProgramError, ProgramData, ProgramError,
}, },
sys::{kernel_version, perf_event_open_probe, perf_event_open_trace_point}, sys::{kernel_version, perf_event_open_probe, perf_event_open_trace_point},
}; };
@ -60,10 +61,12 @@ pub(crate) fn attach<T: Link + From<PerfLink>>(
pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> { pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> {
use ProbeKind::*; use ProbeKind::*;
let tracefs = get_tracefs()?;
match kind { match kind {
KProbe | KRetProbe => delete_probe_event(kind, event_alias) KProbe | KRetProbe => delete_probe_event(tracefs, kind, event_alias)
.map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?, .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
UProbe | URetProbe => delete_probe_event(kind, event_alias) UProbe | URetProbe => delete_probe_event(tracefs, kind, event_alias)
.map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?, .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
}; };
@ -115,15 +118,17 @@ fn create_as_trace_point(
) -> Result<(i32, String), ProgramError> { ) -> Result<(i32, String), ProgramError> {
use ProbeKind::*; use ProbeKind::*;
let tracefs = get_tracefs()?;
let event_alias = match kind { let event_alias = match kind {
KProbe | KRetProbe => create_probe_event(kind, name, offset) KProbe | KRetProbe => create_probe_event(tracefs, kind, name, offset)
.map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?, .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
UProbe | URetProbe => create_probe_event(kind, name, offset) UProbe | URetProbe => create_probe_event(tracefs, kind, name, offset)
.map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?, .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
}; };
let category = format!("{}s", kind.pmu()); let category = format!("{}s", kind.pmu());
let tpid = read_sys_fs_trace_point_id(&category, &event_alias)?; let tpid = read_sys_fs_trace_point_id(tracefs, &category, &event_alias)?;
let fd = perf_event_open_trace_point(tpid, pid).map_err(|(_code, io_error)| { let fd = perf_event_open_trace_point(tpid, pid).map_err(|(_code, io_error)| {
ProgramError::SyscallError { ProgramError::SyscallError {
call: "perf_event_open".to_owned(), call: "perf_event_open".to_owned(),
@ -135,13 +140,14 @@ fn create_as_trace_point(
} }
fn create_probe_event( fn create_probe_event(
tracefs: &Path,
kind: ProbeKind, kind: ProbeKind,
fn_name: &str, fn_name: &str,
offset: u64, offset: u64,
) -> Result<String, (String, io::Error)> { ) -> Result<String, (String, io::Error)> {
use ProbeKind::*; use ProbeKind::*;
let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu()); let events_file_name = tracefs.join(format!("{}_events", kind.pmu()));
let probe_type_prefix = match kind { let probe_type_prefix = match kind {
KProbe | UProbe => 'p', KProbe | UProbe => 'p',
KRetProbe | URetProbe => 'r', KRetProbe | URetProbe => 'r',
@ -170,20 +176,24 @@ fn create_probe_event(
let mut events_file = OpenOptions::new() let mut events_file = OpenOptions::new()
.append(true) .append(true)
.open(&events_file_name) .open(&events_file_name)
.map_err(|e| (events_file_name.clone(), e))?; .map_err(|e| (events_file_name.display().to_string(), e))?;
events_file events_file
.write_all(probe.as_bytes()) .write_all(probe.as_bytes())
.map_err(|e| (events_file_name.clone(), e))?; .map_err(|e| (events_file_name.display().to_string(), e))?;
Ok(event_alias) Ok(event_alias)
} }
fn delete_probe_event(kind: ProbeKind, event_alias: &str) -> Result<(), (String, io::Error)> { fn delete_probe_event(
let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu()); tracefs: &Path,
kind: ProbeKind,
event_alias: &str,
) -> Result<(), (String, io::Error)> {
let events_file_name = tracefs.join(format!("{}_events", kind.pmu()));
let events = let events = fs::read_to_string(&events_file_name)
fs::read_to_string(&events_file_name).map_err(|e| (events_file_name.clone(), e))?; .map_err(|e| (events_file_name.display().to_string(), e))?;
let found = events.lines().any(|line| line.contains(event_alias)); let found = events.lines().any(|line| line.contains(event_alias));
@ -191,13 +201,13 @@ fn delete_probe_event(kind: ProbeKind, event_alias: &str) -> Result<(), (String,
let mut events_file = OpenOptions::new() let mut events_file = OpenOptions::new()
.append(true) .append(true)
.open(&events_file_name) .open(&events_file_name)
.map_err(|e| (events_file_name.to_string(), e))?; .map_err(|e| (events_file_name.display().to_string(), e))?;
let rm = format!("-:{event_alias}\n"); let rm = format!("-:{event_alias}\n");
events_file events_file
.write_all(rm.as_bytes()) .write_all(rm.as_bytes())
.map_err(|e| (events_file_name.to_string(), e))?; .map_err(|e| (events_file_name.display().to_string(), e))?;
} }
Ok(()) Ok(())

@ -1,5 +1,5 @@
//! Tracepoint programs. //! Tracepoint programs.
use std::{fs, io}; use std::{fs, io, path::Path};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
@ -12,6 +12,8 @@ use crate::{
sys::perf_event_open_trace_point, sys::perf_event_open_trace_point,
}; };
use super::utils::get_tracefs;
/// The type returned when attaching a [`TracePoint`] fails. /// The type returned when attaching a [`TracePoint`] fails.
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum TracePointError { pub enum TracePointError {
@ -77,7 +79,8 @@ impl TracePoint {
/// ///
/// The returned value can be used to detach, see [TracePoint::detach]. /// The returned value can be used to detach, see [TracePoint::detach].
pub fn attach(&mut self, category: &str, name: &str) -> Result<TracePointLinkId, ProgramError> { pub fn attach(&mut self, category: &str, name: &str) -> Result<TracePointLinkId, ProgramError> {
let id = read_sys_fs_trace_point_id(category, name)?; let tracefs = get_tracefs()?;
let id = read_sys_fs_trace_point_id(tracefs, category, name)?;
let fd = perf_event_open_trace_point(id, None).map_err(|(_code, io_error)| { let fd = perf_event_open_trace_point(id, None).map_err(|(_code, io_error)| {
ProgramError::SyscallError { ProgramError::SyscallError {
call: "perf_event_open".to_owned(), call: "perf_event_open".to_owned(),
@ -114,20 +117,21 @@ define_link_wrapper!(
); );
pub(crate) fn read_sys_fs_trace_point_id( pub(crate) fn read_sys_fs_trace_point_id(
tracefs: &Path,
category: &str, category: &str,
name: &str, name: &str,
) -> Result<u32, TracePointError> { ) -> Result<u32, TracePointError> {
let file = format!("/sys/kernel/debug/tracing/events/{category}/{name}/id"); let file = tracefs.join("events").join(category).join(name).join("id");
let id = fs::read_to_string(&file).map_err(|io_error| TracePointError::FileError { let id = fs::read_to_string(&file).map_err(|io_error| TracePointError::FileError {
filename: file.clone(), filename: file.display().to_string(),
io_error, io_error,
})?; })?;
let id = id let id = id
.trim() .trim()
.parse::<u32>() .parse::<u32>()
.map_err(|error| TracePointError::FileError { .map_err(|error| TracePointError::FileError {
filename: file.clone(), filename: file.display().to_string(),
io_error: io::Error::new(io::ErrorKind::Other, error), io_error: io::Error::new(io::ErrorKind::Other, error),
})?; })?;

@ -1,5 +1,5 @@
//! Common functions shared between multiple eBPF program types. //! Common functions shared between multiple eBPF program types.
use std::{ffi::CStr, os::unix::io::RawFd}; use std::{ffi::CStr, os::unix::io::RawFd, path::Path};
use crate::{ use crate::{
programs::{FdLink, Link, ProgramData, ProgramError}, programs::{FdLink, Link, ProgramData, ProgramError},
@ -22,3 +22,25 @@ pub(crate) fn attach_raw_tracepoint<T: Link + From<FdLink>>(
program_data.links.insert(FdLink::new(pfd).into()) program_data.links.insert(FdLink::new(pfd).into())
} }
// Get tracefs filesystem
pub(crate) fn get_tracefs() -> Result<&'static Path, ProgramError> {
lazy_static::lazy_static! {
static ref TRACE_FS: Option<&'static Path> = {
let mounts = [
Path::new("/sys/kernel/tracing"),
Path::new("/sys/kernel/debug/tracing"),
];
for mount in mounts {
if mount.exists() {
return Some(mount);
}
}
None
};
}
TRACE_FS.as_deref().ok_or(ProgramError::TraceFsNotFound)
}

Loading…
Cancel
Save