in src/samplers/usercall/mod.rs [99:220]
fn init_bpf(&mut self) -> Result<(), anyhow::Error> {
// The bpf source code generated by probe_template
let mut bpf_probes = String::new();
// The list of probes that have been found.
let mut found_probes: Vec<(String, String, String)> = Vec::new();
// Add probes that are linked to specific files in the config
for probe_config in self.libraries.iter().filter(|x| x.path.is_some()) {
for func in probe_config.functions.iter() {
#[allow(clippy::format_in_format_args)]
bpf_probes.push_str(&format!(
probe_template!(),
found_probes.len(),
format!("{}/{}/{}", NAMESPACE, probe_config.name, func)
));
found_probes.push((
probe_config.path.as_ref().unwrap().clone(),
probe_config.name.clone(),
func.clone(),
));
}
}
// Add probes by searching the default paths.
let entries: Vec<walkdir::DirEntry> = DEFAULT_LIB_SEARCH_PATHS
.iter()
.map(|p| {
walkdir::WalkDir::new(p)
.follow_links(true)
.into_iter()
.filter_map(|e| e.ok())
})
.flatten()
.collect();
for probe_config in self.libraries.iter().filter(|x| x.path.is_none()) {
let mut found = false;
for entry in &entries {
if path_match(&probe_config.name, entry.path()) {
for func in probe_config.functions.iter() {
#[allow(clippy::format_in_format_args)]
bpf_probes.push_str(&format!(
probe_template!(),
found_probes.len(),
format!("{}/{}/{}", NAMESPACE, probe_config.name, func)
));
found_probes.push((
entry.path().to_string_lossy().to_string(),
probe_config.name.clone(),
func.clone(),
));
}
found = true;
break;
}
}
if !found {
let err = std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("probe not found {:?}", probe_config),
);
if self.common.config().fault_tolerant() {
for func in probe_config.functions.iter() {
let stat_name = format!("{}/{}/{}", NAMESPACE, probe_config.name, func);
self.statistics.retain(|s| s.stat_path != stat_name);
}
warn!("{}", err);
} else {
return Err(err.into());
}
}
}
#[cfg(feature = "bpf")]
{
debug!("Registering probes: {:?}", found_probes);
// Build the bpf program by appending all the bpf_probe source to the prelude
let bpf_prog = PROBE_PRELUDE.to_string() + &bpf_probes;
let mut bpf = bcc::BPF::new(&bpf_prog)?;
for (i, probe) in found_probes.iter().enumerate() {
let (path, lib, func) = probe;
if let Err(e) = bcc::Uprobe::new()
.handler(&format!("probe_{}", i))
.binary(path)
.symbol(func)
.attach(&mut bpf)
{
let err = match std::fs::metadata(path) {
Ok(md) => {
if md.is_file() {
std::io::Error::new(
std::io::ErrorKind::Other,
format!("problem probing {:?}: {}", probe, e),
)
} else {
std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("problem probing {:?}: Not a file: {}", probe, path),
)
}
}
Err(e) => std::io::Error::new(
std::io::ErrorKind::Other,
format!("problem probing {:?}: {}", probe, e),
),
};
if self.common.config().fault_tolerant() {
let stat_name = format!("{}/{}/{}", NAMESPACE, lib, func);
self.statistics.retain(|s| s.stat_path != stat_name);
warn!("{}", err);
} else {
Err(err)?
}
};
}
self.bpf = Some(Arc::new(Mutex::new(BPF { inner: bpf })));
}
Ok(())
}