fn init_bpf()

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