Skip to main content

scx_lavd/
bpf_streams.rs

1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (c) 2026 Meta Platforms
4
5use crate::BpfSkel;
6use libbpf_rs::skel::Skel;
7use libbpf_rs::ProgramType;
8use std::io::Read;
9use std::io::Write;
10
11fn dump_program_stream(
12    prog_name: &str,
13    stream_name: &str,
14    mut stream: impl Read,
15    stderr: bool,
16) -> std::io::Result<bool> {
17    let mut buf = Vec::new();
18    stream.read_to_end(&mut buf)?;
19
20    let body = String::from_utf8_lossy(&buf);
21    if body.len() == 0 {
22        return Ok(false);
23    }
24
25    let stream_label = stream_name.to_ascii_uppercase();
26    if stderr {
27        eprintln!("\n===BEGIN BPF {stream_label} {prog_name}===");
28        eprint!("{body}");
29        eprintln!("\n====END BPF {stream_label} {prog_name}====");
30        std::io::stderr().flush()?;
31    } else {
32        println!("\n===BEGIN BPF {stream_label} {prog_name}===");
33        print!("{body}");
34        println!("\n====END BPF {stream_label} {prog_name}====");
35        std::io::stdout().flush()?;
36    }
37
38    Ok(!buf.is_empty())
39}
40
41pub(crate) fn dump_bpf_streams(skel: &mut BpfSkel<'_>) {
42    let mut dumped = false;
43    let mut unavailable = false;
44
45    for prog in skel
46        .object()
47        .progs_mut()
48        .filter(|prog| prog.prog_type() == ProgramType::StructOps)
49    {
50        let prog_name = prog.name().to_string_lossy();
51
52        match dump_program_stream(prog_name.as_ref(), "stdout", prog.stdout(), false) {
53            Ok(stream_dumped) => dumped |= stream_dumped,
54            Err(_) => unavailable = true,
55        }
56
57        match dump_program_stream(prog_name.as_ref(), "stderr", prog.stderr(), true) {
58            Ok(stream_dumped) => dumped |= stream_dumped,
59            Err(_) => unavailable = true,
60        }
61    }
62
63    if !dumped && unavailable {
64        eprintln!("BPF stream dump unavailable (requires kernel/libbpf support for BPF streams)");
65    }
66}