|  | @@ -1,6 +1,6 @@
 | 
	
		
			
				|  |  |  use libc::pid_t;
 | 
	
		
			
				|  |  |  use std::{
 | 
	
		
			
				|  |  | -    fs,
 | 
	
		
			
				|  |  | +    fs::{self, OpenOptions},
 | 
	
		
			
				|  |  |      io::{self, Write},
 | 
	
		
			
				|  |  |      process,
 | 
	
		
			
				|  |  |  };
 | 
	
	
		
			
				|  | @@ -26,6 +26,15 @@ pub enum ProbeKind {
 | 
	
		
			
				|  |  |      URetProbe,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +impl ProbeKind {
 | 
	
		
			
				|  |  | +    fn pmu(&self) -> &'static str {
 | 
	
		
			
				|  |  | +        match *self {
 | 
	
		
			
				|  |  | +            ProbeKind::KProbe | ProbeKind::KRetProbe => "kprobe",
 | 
	
		
			
				|  |  | +            ProbeKind::UProbe | ProbeKind::URetProbe => "uprobe",
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  pub(crate) fn attach(
 | 
	
		
			
				|  |  |      program_data: &mut ProgramData,
 | 
	
		
			
				|  |  |      kind: ProbeKind,
 | 
	
	
		
			
				|  | @@ -50,46 +59,13 @@ pub(crate) fn attach(
 | 
	
		
			
				|  |  |  pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> {
 | 
	
		
			
				|  |  |      use ProbeKind::*;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    /*
 | 
	
		
			
				|  |  | -     * Taken from https://github.com/iovisor/bcc/blob/67f59ee80fcf5deedaacba1436d9fa09d32a16a0/src/cc/libbpf.c#L1173
 | 
	
		
			
				|  |  | -     *
 | 
	
		
			
				|  |  | -     * For [k,u]probe created with perf_event_open (on newer kernel), it is
 | 
	
		
			
				|  |  | -     * not necessary to clean it up in [k,u]probe_events. We first look up
 | 
	
		
			
				|  |  | -     * the %s_bcc_%d line in [k,u]probe_events. If the event is not found,
 | 
	
		
			
				|  |  | -     * it is safe to skip the cleaning up process (write -:... to the file).
 | 
	
		
			
				|  |  | -     */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    let event_type = match kind {
 | 
	
		
			
				|  |  | -        KProbe | KRetProbe => "kprobe",
 | 
	
		
			
				|  |  | -        UProbe | URetProbe => "uprobe",
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", event_type);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    let found = match kind {
 | 
	
		
			
				|  |  | -        KProbe | KRetProbe => {
 | 
	
		
			
				|  |  | -            find_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias)
 | 
	
		
			
				|  |  | -                .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        UProbe | URetProbe => {
 | 
	
		
			
				|  |  | -            find_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias)
 | 
	
		
			
				|  |  | -                .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    let _ = match kind {
 | 
	
		
			
				|  |  | +        KProbe | KRetProbe => delete_probe_event(kind, event_alias)
 | 
	
		
			
				|  |  | +            .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  | +        UProbe | URetProbe => delete_probe_event(kind, event_alias)
 | 
	
		
			
				|  |  | +            .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if found {
 | 
	
		
			
				|  |  | -        match kind {
 | 
	
		
			
				|  |  | -            KProbe | KRetProbe => {
 | 
	
		
			
				|  |  | -                delete_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias)
 | 
	
		
			
				|  |  | -                    .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            UProbe | URetProbe => {
 | 
	
		
			
				|  |  | -                delete_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias)
 | 
	
		
			
				|  |  | -                    .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      Ok(())
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -102,19 +78,19 @@ fn create_as_probe(
 | 
	
		
			
				|  |  |      use ProbeKind::*;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      let perf_ty = match kind {
 | 
	
		
			
				|  |  | -        KProbe | KRetProbe => read_sys_fs_perf_type("kprobe")
 | 
	
		
			
				|  |  | +        KProbe | KRetProbe => read_sys_fs_perf_type(kind.pmu())
 | 
	
		
			
				|  |  |              .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  | -        UProbe | URetProbe => read_sys_fs_perf_type("uprobe")
 | 
	
		
			
				|  |  | +        UProbe | URetProbe => read_sys_fs_perf_type(kind.pmu())
 | 
	
		
			
				|  |  |              .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      let ret_bit = match kind {
 | 
	
		
			
				|  |  |          KRetProbe => Some(
 | 
	
		
			
				|  |  | -            read_sys_fs_perf_ret_probe("kprobe")
 | 
	
		
			
				|  |  | +            read_sys_fs_perf_ret_probe(kind.pmu())
 | 
	
		
			
				|  |  |                  .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  |          ),
 | 
	
		
			
				|  |  |          URetProbe => Some(
 | 
	
		
			
				|  |  | -            read_sys_fs_perf_ret_probe("uprobe")
 | 
	
		
			
				|  |  | +            read_sys_fs_perf_ret_probe(kind.pmu())
 | 
	
		
			
				|  |  |                  .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  |          ),
 | 
	
		
			
				|  |  |          _ => None,
 | 
	
	
		
			
				|  | @@ -138,20 +114,15 @@ fn create_as_trace_point(
 | 
	
		
			
				|  |  |  ) -> Result<(i32, String), ProgramError> {
 | 
	
		
			
				|  |  |      use ProbeKind::*;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let (event_type, event_alias) = match kind {
 | 
	
		
			
				|  |  | -        KProbe | KRetProbe => (
 | 
	
		
			
				|  |  | -            "kprobes",
 | 
	
		
			
				|  |  | -            create_probe_event(kind, "kprobe", name, offset)
 | 
	
		
			
				|  |  | -                .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  | -        ),
 | 
	
		
			
				|  |  | -        UProbe | URetProbe => (
 | 
	
		
			
				|  |  | -            "uprobes",
 | 
	
		
			
				|  |  | -            create_probe_event(kind, "uprobe", name, offset)
 | 
	
		
			
				|  |  | -                .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  | -        ),
 | 
	
		
			
				|  |  | +    let event_alias = match kind {
 | 
	
		
			
				|  |  | +        KProbe | KRetProbe => create_probe_event(kind, name, offset)
 | 
	
		
			
				|  |  | +            .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  | +        UProbe | URetProbe => create_probe_event(kind, name, offset)
 | 
	
		
			
				|  |  | +            .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?,
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let tpid = read_sys_fs_trace_point_id(event_type, &event_alias)?;
 | 
	
		
			
				|  |  | +    let category = format!("{}s", kind.pmu());
 | 
	
		
			
				|  |  | +    let tpid = read_sys_fs_trace_point_id(&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(),
 | 
	
	
		
			
				|  | @@ -164,93 +135,69 @@ fn create_as_trace_point(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fn create_probe_event(
 | 
	
		
			
				|  |  |      kind: ProbeKind,
 | 
	
		
			
				|  |  | -    event_type: &str,
 | 
	
		
			
				|  |  |      fn_name: &str,
 | 
	
		
			
				|  |  |      offset: u64,
 | 
	
		
			
				|  |  |  ) -> Result<String, (String, io::Error)> {
 | 
	
		
			
				|  |  |      use ProbeKind::*;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", event_type);
 | 
	
		
			
				|  |  | +    let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu());
 | 
	
		
			
				|  |  |      let probe_type_prefix = match kind {
 | 
	
		
			
				|  |  |          KProbe | UProbe => 'p',
 | 
	
		
			
				|  |  |          KRetProbe | URetProbe => 'r',
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    let event_alias = format!("{}_{}_aya_{}", probe_type_prefix, fn_name, process::id());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    let mut events_file = fs::OpenOptions::new()
 | 
	
		
			
				|  |  | +    let event_alias = format!(
 | 
	
		
			
				|  |  | +        "aya_{}_{}_{}_{:#x}",
 | 
	
		
			
				|  |  | +        process::id(),
 | 
	
		
			
				|  |  | +        probe_type_prefix,
 | 
	
		
			
				|  |  | +        fn_name,
 | 
	
		
			
				|  |  | +        offset
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +    let offset_suffix = match kind {
 | 
	
		
			
				|  |  | +        KProbe => format!("+{}", offset),
 | 
	
		
			
				|  |  | +        UProbe => format!(":{:#x}", offset),
 | 
	
		
			
				|  |  | +        _ => "".to_string(),
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    let probe = format!(
 | 
	
		
			
				|  |  | +        "{}:{}s/{} {}{}\n",
 | 
	
		
			
				|  |  | +        probe_type_prefix,
 | 
	
		
			
				|  |  | +        kind.pmu(),
 | 
	
		
			
				|  |  | +        event_alias,
 | 
	
		
			
				|  |  | +        fn_name,
 | 
	
		
			
				|  |  | +        offset_suffix
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let mut events_file = OpenOptions::new()
 | 
	
		
			
				|  |  |          .append(true)
 | 
	
		
			
				|  |  |          .open(&events_file_name)
 | 
	
		
			
				|  |  |          .map_err(|e| (events_file_name.clone(), e))?;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let p = match kind {
 | 
	
		
			
				|  |  | -        KProbe => {
 | 
	
		
			
				|  |  | -            if offset > 0 {
 | 
	
		
			
				|  |  | -                format!(
 | 
	
		
			
				|  |  | -                    "{}:{}s/{} {}+{}",
 | 
	
		
			
				|  |  | -                    probe_type_prefix, event_type, event_alias, fn_name, offset
 | 
	
		
			
				|  |  | -                )
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                format!(
 | 
	
		
			
				|  |  | -                    "{}:{}s/{} {}",
 | 
	
		
			
				|  |  | -                    probe_type_prefix, event_type, event_alias, fn_name
 | 
	
		
			
				|  |  | -                )
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        KRetProbe => format!(
 | 
	
		
			
				|  |  | -            "{}:{}s/{} {}",
 | 
	
		
			
				|  |  | -            probe_type_prefix, event_type, event_alias, fn_name
 | 
	
		
			
				|  |  | -        ),
 | 
	
		
			
				|  |  | -        UProbe | URetProbe => {
 | 
	
		
			
				|  |  | -            if offset > 0 {
 | 
	
		
			
				|  |  | -                format!(
 | 
	
		
			
				|  |  | -                    "{}:{}s/{} {}:{:#x}",
 | 
	
		
			
				|  |  | -                    probe_type_prefix, event_type, event_alias, fn_name, offset
 | 
	
		
			
				|  |  | -                )
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                format!(
 | 
	
		
			
				|  |  | -                    "{}:{}s/{} {}",
 | 
	
		
			
				|  |  | -                    probe_type_prefix, event_type, event_alias, fn_name
 | 
	
		
			
				|  |  | -                )
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      events_file
 | 
	
		
			
				|  |  | -        .write_all(p.as_bytes())
 | 
	
		
			
				|  |  | +        .write_all(probe.as_bytes())
 | 
	
		
			
				|  |  |          .map_err(|e| (events_file_name.clone(), e))?;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      Ok(event_alias)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn find_in_sys_kernel_debug_tracing_events(
 | 
	
		
			
				|  |  | -    events_file_name: &str,
 | 
	
		
			
				|  |  | -    event_alias: &str,
 | 
	
		
			
				|  |  | -) -> Result<bool, (String, io::Error)> {
 | 
	
		
			
				|  |  | -    use std::io::BufRead;
 | 
	
		
			
				|  |  | +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());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let events_file =
 | 
	
		
			
				|  |  | -        fs::File::open(events_file_name).map_err(|e| (events_file_name.to_string(), e))?;
 | 
	
		
			
				|  |  | +    let events =
 | 
	
		
			
				|  |  | +        fs::read_to_string(&events_file_name).map_err(|e| (events_file_name.clone(), e))?;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    Ok(io::BufReader::new(events_file)
 | 
	
		
			
				|  |  | -        .lines()
 | 
	
		
			
				|  |  | -        .map(|line| line.unwrap())
 | 
	
		
			
				|  |  | -        .any(|line| line.contains(event_alias)))
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +    let found = events.lines().any(|line| line.contains(event_alias));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn delete_in_sys_kernel_debug_tracing_events(
 | 
	
		
			
				|  |  | -    events_file_name: &str,
 | 
	
		
			
				|  |  | -    event_alias: &str,
 | 
	
		
			
				|  |  | -) -> Result<(), (String, io::Error)> {
 | 
	
		
			
				|  |  | -    let mut events_file = fs::OpenOptions::new()
 | 
	
		
			
				|  |  | -        .append(true)
 | 
	
		
			
				|  |  | -        .open(events_file_name)
 | 
	
		
			
				|  |  | -        .map_err(|e| (events_file_name.to_string(), e))?;
 | 
	
		
			
				|  |  | +    if found {
 | 
	
		
			
				|  |  | +        let mut events_file = OpenOptions::new()
 | 
	
		
			
				|  |  | +            .append(true)
 | 
	
		
			
				|  |  | +            .open(&events_file_name)
 | 
	
		
			
				|  |  | +            .map_err(|e| (events_file_name.to_string(), e))?;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let rm = format!("-:{}", event_alias);
 | 
	
		
			
				|  |  | +        let rm = format!("-:{}\n", event_alias);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    events_file
 | 
	
		
			
				|  |  | -        .write_all(rm.as_bytes())
 | 
	
		
			
				|  |  | -        .map_err(|e| (events_file_name.to_string(), e))?;
 | 
	
		
			
				|  |  | +        events_file
 | 
	
		
			
				|  |  | +            .write_all(rm.as_bytes())
 | 
	
		
			
				|  |  | +            .map_err(|e| (events_file_name.to_string(), e))?;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      Ok(())
 | 
	
		
			
				|  |  |  }
 |