Skip to content

Commit

Permalink
Test
Browse files Browse the repository at this point in the history
  • Loading branch information
d-e-s-o committed Oct 17, 2024
1 parent 8003e4b commit 4079a9b
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
109 changes: 109 additions & 0 deletions src/kernel/bpf/prog.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::Debug;
use std::path::Path;
use std::rc::Rc;

use crate::inspect::SymInfo;
use crate::once::OnceCell;
use crate::symbolize::ResolvedSym;
use crate::symbolize::SrcLang;
use crate::Addr;
Expand All @@ -20,12 +24,21 @@ pub type BpfTag = u64;
const _: () = assert!(size_of::<BpfTag>() == BPF_TAG_SIZE);


#[derive(Debug)]
struct LineInfoRecord {
file: Rc<Path>,
line: Option<u32>,
col: Option<u16>,
}


/// Information about a BPF program.
#[derive(Debug)]
pub struct BpfProg {
addr: Addr,
name: Box<str>,
tag: BpfTag,
line_info: OnceCell<HashMap<Addr, LineInfoRecord>>,
}

impl BpfProg {
Expand All @@ -44,6 +57,7 @@ impl BpfProg {
addr,
name: Box::from(name),
tag,
line_info: OnceCell::new(),
};
Some(prog)
}
Expand Down Expand Up @@ -102,11 +116,25 @@ impl<'prog> TryFrom<&'prog BpfProg> for SymInfo<'prog> {

#[cfg(test)]
mod tests {
use crate::ErrorExt as _;

use super::*;

use std::collections::hash_map::Entry;
use std::ffi::CStr;
use std::os::fd::AsFd as _;
use std::os::fd::AsRawFd as _;
use std::os::fd::BorrowedFd;
use std::path::PathBuf;

use test_log::test;
use test_tag::tag;

use crate::Result;

use super::super::sys;
use super::super::Btf;


/// Test that we can parse a BPF program string as it may appear in
/// `kallsyms` successfully.
Expand All @@ -126,4 +154,85 @@ mod tests {
let name = "bpf_prog_get_curr_or_next";
assert!(BpfProg::parse(name, addr).is_none());
}

// https://www.kernel.org/doc/html/latest/bpf/btf.html#bpf-prog-load
fn query_line_info(
bpf_fd: BorrowedFd<'_>,
info: &sys::bpf_prog_info,
) -> Result<HashMap<Addr, (PathBuf, u32, u16)>> {
let name = CStr::from_bytes_until_nul(info.name.as_slice())
.unwrap()
.to_string_lossy();

assert_eq!(
info.line_info_rec_size,
size_of::<sys::bpf_line_info>() as _
);
let mut line_info = Vec::<sys::bpf_line_info>::with_capacity(info.nr_line_info as _);
// SAFETY: `bpf_line_info` is valid for any bit pattern, so we
// can adjust the vector's length to its capacity.
let () = unsafe { line_info.set_len(line_info.capacity()) };

assert_eq!(info.jited_line_info_rec_size, size_of::<u64>() as _);
let mut jited_line_info = Vec::<u64>::with_capacity(info.nr_jited_line_info as _);
// SAFETY: `u64` is valid for any bit pattern, so we can adjust
// the vector's length to its capacity.
let () = unsafe { jited_line_info.set_len(jited_line_info.capacity()) };

let mut info = sys::bpf_prog_info {
nr_line_info: info.nr_line_info,
line_info_rec_size: info.line_info_rec_size,
line_info: line_info.as_mut_ptr() as _,
nr_jited_line_info: info.nr_jited_line_info,
jited_line_info_rec_size: info.jited_line_info_rec_size,
jited_line_info: jited_line_info.as_mut_ptr() as _,
..Default::default()
};
let () = sys::bpf_prog_get_info_from_fd(bpf_fd.as_raw_fd(), &mut info).unwrap();

let mut file_cache = HashMap::new();
let btf = Btf::load_from_id(info.btf_id)
.with_context(|| format!("failed to load BTF information for program `{name}`"))?;
for (i, addr) in jited_line_info.into_iter().enumerate() {
let info = line_info.get(i).unwrap();
let file = btf.name(info.file_name_off).unwrap();

// Check if we already have the file cached (and do so if
// not), to not have dozens of duplicate allocations flying
// around.
let path = match file_cache.entry(file) {
Entry::Vacant(vacancy) => {
let path = Rc::<Path>::from(PathBuf::from(file).into_boxed_path());
vacancy.insert(path)
}
Entry::Occupied(occupancy) => occupancy.into_mut(),
};

let line = info.line();
let col = info.column();
println!("{addr:#x}\t: {path:?}:{line}:{col}");
}
Ok(HashMap::new())
}

/// XXX
#[test]
fn foobar() {
let mut next_prog_id = 0;
while let Ok(prog_id) = sys::bpf_prog_get_next_id(next_prog_id) {
let fd = sys::bpf_prog_get_fd_from_id(prog_id).unwrap();

let mut info = sys::bpf_prog_info::default();
let () = sys::bpf_prog_get_info_from_fd(fd.as_raw_fd(), &mut info).unwrap();

println!(
"found BPF program: {}",
CStr::from_bytes_until_nul(info.name.as_slice())
.unwrap()
.to_string_lossy()
);
let _map = query_line_info(fd.as_fd(), &info).unwrap();
next_prog_id = prog_id;
}
}
}
9 changes: 8 additions & 1 deletion src/symbolize/symbolizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,13 @@ mod tests {
#[test]
fn symbolize_kernel_bpf_program() {
let addr = bpf_symbolization_target_addr();
println!("BPF address: {addr:#x}");
let src = symbolize::Source::Kernel(symbolize::Kernel::default());
let symbolizer = Symbolizer::new();
let result = symbolizer
.symbolize_single(&src, symbolize::Input::AbsAddr(addr))
.unwrap()
.into_sym()
.unwrap();
assert_eq!(result.name, "");
}
}

0 comments on commit 4079a9b

Please sign in to comment.