Refactoring after feedback.

pull/108/head
Dan Everton 3 years ago
parent 606c3267c4
commit 0e84610976
No known key found for this signature in database
GPG Key ID: 2AF33A2B189A11B3

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

@ -80,7 +80,10 @@ impl TracePoint {
} }
} }
pub fn read_sys_fs_trace_point_id(category: &str, name: &str) -> Result<u32, TracePointError> { pub(crate) fn read_sys_fs_trace_point_id(
category: &str,
name: &str,
) -> Result<u32, TracePointError> {
let file = format!("/sys/kernel/debug/tracing/events/{}/{}/id", category, name); let file = format!("/sys/kernel/debug/tracing/events/{}/{}/id", category, name);
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 {

Loading…
Cancel
Save