Browse Source

feat: get_tracefs function

banditopazzo 2 years ago
parent
commit
c6c4ac7eea
4 changed files with 62 additions and 22 deletions
  1. 4 0
      aya/src/programs/mod.rs
  2. 26 16
      aya/src/programs/probe.rs
  3. 9 5
      aya/src/programs/trace_point.rs
  4. 23 1
      aya/src/programs/utils.rs

+ 4 - 0
aya/src/programs/mod.rs

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

+ 26 - 16
aya/src/programs/probe.rs

@@ -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(())

+ 9 - 5
aya/src/programs/trace_point.rs

@@ -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),
         })?;
 

+ 23 - 1
aya/src/programs/utils.rs

@@ -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)
+}