feat: get_tracefs function

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

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

@ -2,14 +2,15 @@ use libc::pid_t;
use std::{
fs::{self, OpenOptions},
io::{self, Write},
path::Path,
process,
};
use crate::{
programs::{
kprobe::KProbeError, perf_attach, perf_attach::PerfLink, perf_attach_debugfs,
trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, Link, ProgramData,
ProgramError,
trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, utils::get_tracefs, Link,
ProgramData, ProgramError,
},
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> {
use ProbeKind::*;
let tracefs = get_tracefs()?;
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 })?,
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 })?,
};
@ -115,15 +118,17 @@ fn create_as_trace_point(
) -> Result<(i32, String), ProgramError> {
use ProbeKind::*;
let tracefs = get_tracefs()?;
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 })?,
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 })?,
};
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)| {
ProgramError::SyscallError {
call: "perf_event_open".to_owned(),
@ -135,13 +140,14 @@ fn create_as_trace_point(
}
fn create_probe_event(
tracefs: &Path,
kind: ProbeKind,
fn_name: &str,
offset: u64,
) -> Result<String, (String, io::Error)> {
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 {
KProbe | UProbe => 'p',
KRetProbe | URetProbe => 'r',
@ -170,20 +176,24 @@ fn create_probe_event(
let mut events_file = OpenOptions::new()
.append(true)
.open(&events_file_name)
.map_err(|e| (events_file_name.clone(), e))?;
.map_err(|e| (events_file_name.display().to_string(), e))?;
events_file
.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)
}
fn delete_probe_event(kind: ProbeKind, event_alias: &str) -> Result<(), (String, io::Error)> {
let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu());
fn delete_probe_event(
tracefs: &Path,
kind: ProbeKind,
event_alias: &str,
) -> Result<(), (String, io::Error)> {
let events_file_name = tracefs.join(format!("{}_events", kind.pmu()));
let events =
fs::read_to_string(&events_file_name).map_err(|e| (events_file_name.clone(), e))?;
let events = fs::read_to_string(&events_file_name)
.map_err(|e| (events_file_name.display().to_string(), e))?;
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()
.append(true)
.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");
events_file
.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(())

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

@ -1,5 +1,5 @@
//! 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::{
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())
}
// 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