Skip to content

Commit

Permalink
fixup! 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 abdfd54 commit cc13756
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 27 deletions.
81 changes: 58 additions & 23 deletions src/kernel/bpf/prog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ use std::os::fd::BorrowedFd;
use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FmtResult;


use crate::inspect::SymInfo;
use crate::once::OnceCell;
Expand All @@ -30,12 +34,46 @@ use super::Btf;
/// BPF kernel programs show up with this prefix followed by a tag and
/// some other meta-data.
const BPF_PROG_PREFIX: &str = "bpf_prog_";
/// The size of a BPF tag, as defined in `include/uapi/linux/bpf.h`.
const BPF_TAG_SIZE: usize = 8;

pub type BpfTag = u64;

const _: () = assert!(size_of::<BpfTag>() == BPF_TAG_SIZE);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct BpfTag([u8; 8]);

impl Display for BpfTag {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
for b in self.0 {
let () = write!(f, "{b:02x}")?;
}
Ok(())
}
}

impl From<[u8; 8]> for BpfTag {
fn from(other: [u8; 8]) -> Self {
Self(other)
}
}

use std::str::FromStr;

impl FromStr for BpfTag {
type Err = ();

fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.as_bytes().len() != 2 * size_of::<BpfTag>() {
return Err(())
}

let mut tag = [0; size_of::<BpfTag>()];
(0..s.len())
.step_by(2)
.enumerate()
.try_for_each(|(i, idx)| tag[i] = u8::from_str_radix(&s[i..i + 2], 16).map_err(|_| ())?)?;

Ok(Self(tag))
}
}


/// A cache for BPF program related information.
Expand All @@ -54,15 +92,11 @@ pub struct BpfInfoCache {
}

impl BpfInfoCache {
/// Look up BPF program information from the cache and remove it.
///
/// We remove the information to keep memory usage to a minimum:
/// we expect clients of this infrastructure to extract and then
/// cache their own copy of data from the `bpf_prog_info`.
fn lookup_and_take(&self, tag: BpfTag) -> Result<Option<sys::bpf_prog_info>> {
/// Look up BPF program information from the cache.
fn lookup(&self, tag: BpfTag) -> Result<Option<sys::bpf_prog_info>> {
let mut cache = self.cache.borrow_mut();
if let Some(info) = cache.remove(&tag) {
return Ok(Some(info))
if let Some(info) = cache.get(&tag) {
return Ok(Some(*info))
}

// If we didn't find the tag inside the cache we have to assume
Expand All @@ -75,6 +109,7 @@ impl BpfInfoCache {
let mut next_prog_id = 0;

while let Ok(prog_id) = sys::bpf_prog_get_next_id(next_prog_id) {
println!("FOUND PROG {prog_id}");
let fd = sys::bpf_prog_get_fd_from_id(prog_id).with_context(|| {
format!("failed to retrieve BPF program file descriptor for program {prog_id}")
})?;
Expand All @@ -88,9 +123,14 @@ impl BpfInfoCache {
let prog_tag = BpfTag::from_ne_bytes(info.tag);
if found.is_none() && tag == prog_tag {
found = Some(info);
} else {
let _prev = cache.insert(prog_tag, info);
}

let name = std::ffi::CStr::from_bytes_until_nul(info.name.as_slice())
.unwrap()
.to_string_lossy();

println!("NAME: `{name}` | TAG {prog_tag:#x}");
let _prev = cache.insert(prog_tag, info);
next_prog_id = prog_id;
}
Ok(found)
Expand Down Expand Up @@ -205,12 +245,7 @@ impl BpfProg {
pub fn parse(s: &str, addr: Addr) -> Option<Self> {
let s = s.strip_prefix(BPF_PROG_PREFIX)?;
let (tag, name) = s.split_once('_')?;
// Each byte of the tag is encoded as two hexadecimal characters.
if tag.len() != 2 * BPF_TAG_SIZE {
return None
}

let tag = BpfTag::from_str_radix(tag, 16).ok()?;
let tag = BpfTag::from_str(tag).ok()?;
let prog = BpfProg {
addr,
name: Box::from(name),
Expand All @@ -228,9 +263,9 @@ impl BpfProg {
) -> Result<ResolvedSym<'_>> {
let code_info = if opts.code_info() {
let line_info = self.line_info.get_or_try_init(|| {
let prog_info = info_cache.lookup_and_take(self.tag)?.ok_or_not_found(|| {
let prog_info = info_cache.lookup(self.tag)?.ok_or_not_found(|| {
format!(
"failed to information for BPF program with tag {:#x}",
"failed to find information for BPF program with tag {}",
self.tag
)
})?;
Expand Down Expand Up @@ -363,7 +398,7 @@ mod tests {
let tag = BpfTag::from_ne_bytes(info.tag);

let cache = BpfInfoCache::default();
let info = cache.lookup_and_take(tag).unwrap().unwrap();
let info = cache.lookup(tag).unwrap().unwrap();

assert_eq!(BpfTag::from_ne_bytes(info.tag), tag);
}
Expand Down
4 changes: 4 additions & 0 deletions src/symbolize/symbolizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,10 @@ mod tests {
#[test]
fn symbolize_kernel_bpf_program() {
with_bpf_symbolization_target_addr(|addr| {
println!("ADDRESS: {addr:#x}");
let mut buffer = String::new();
std::io::stdin().read_line(&mut buffer).unwrap();

let src = symbolize::Source::Kernel(symbolize::Kernel::default());
let symbolizer = Symbolizer::new();
let result = symbolizer
Expand Down
12 changes: 8 additions & 4 deletions tests/bpf/src/getpid.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ struct {

static __noinline u64 symbolization_target(void)
{
asm volatile ("");
u64 fp, ip;
/* Read frame pointer. */
asm volatile ("%[fp] = r10" : [fp] "+r"(fp) :);
/* At frame pointer + 8 we expect the return address. */
bpf_probe_read_kernel(&ip, sizeof(ip), (void *)(long)(fp + 8));
return ip;
}

SEC("tracepoint/syscalls/sys_enter_getpid")
Expand All @@ -24,9 +29,8 @@ int handle__getpid(void *ctx)
return 1;
}

(void)symbolization_target();

*value = (u64)&symbolization_target;
(void)&symbolization_target;
*value = symbolization_target();
bpf_printk("symbolization_target = %lx\n", *value);
bpf_ringbuf_submit(value, 0);
bpf_printk("handle__getpid: submitted ringbuf value");
Expand Down

0 comments on commit cc13756

Please sign in to comment.