forked from libbpf/blazesym
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make BPF symbolization tests end-to-end tests
TODO: Does not work because we are attempting to expose dev-only stuff (libbpbf-rs) via the main crate. This may be possible to resolve by moving this functionality into blazesym-dev (but that, in turn, requires more stuff to be exposed from the main crate) The BPF symbolization tests were added as unit tests, because they require a bunch of setup shenanigans that we only had internally to the crate. Conceptually, however, they are very much end-to-end tests that test the public API surface and not just some implementation detail. We *really* want to preserve the ability to get a good overview of all end-to-end tests in a single location and so with this change we take necessary steps to expose necessary test helpers so that they can be used from end-to-end tests. Furthermore, we move said BPF symbolization tests into tests/blazesym.rs, co-located with most other end-to-end tests. Signed-off-by: Daniel Müller <deso@posteo.net>
- Loading branch information
Showing
13 changed files
with
235 additions
and
209 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,124 @@ | ||
#![allow( | ||
clippy::clone_on_ref_ptr, | ||
clippy::collapsible_else_if, | ||
clippy::collapsible_if, | ||
clippy::fn_to_numeric_cast, | ||
clippy::let_and_return, | ||
clippy::let_unit_value | ||
)] | ||
#![deny(unsafe_op_in_unsafe_fn)] | ||
|
||
|
||
#[cfg(linux)] | ||
mod bpf { | ||
use std::path::Path; | ||
use std::path::PathBuf; | ||
|
||
use blazesym::Addr; | ||
use blazesym::__private::ReadRaw as _; | ||
|
||
use libbpf_rs::Map; | ||
use libbpf_rs::MapCore as _; | ||
use libbpf_rs::MapMut; | ||
use libbpf_rs::Object; | ||
use libbpf_rs::ObjectBuilder; | ||
use libbpf_rs::OpenObject; | ||
use libbpf_rs::ProgramMut; | ||
use libbpf_rs::RingBufferBuilder; | ||
|
||
|
||
fn test_object_path(object: &str) -> PathBuf { | ||
Path::new(&env!("CARGO_MANIFEST_DIR")) | ||
.join("..") | ||
.join("tests") | ||
.join("bpf") | ||
.join(object) | ||
} | ||
|
||
#[track_caller] | ||
fn open_test_object(object: &str) -> OpenObject { | ||
let obj_path = test_object_path(object); | ||
let obj = ObjectBuilder::default() | ||
.open_file(obj_path) | ||
.expect("failed to open object"); | ||
obj | ||
} | ||
|
||
#[track_caller] | ||
pub fn test_object(filename: &str) -> Object { | ||
open_test_object(filename) | ||
.load() | ||
.expect("failed to load object") | ||
} | ||
|
||
/// Find the BPF map with the given name, panic if it does not exist. | ||
#[track_caller] | ||
fn map_mut<'obj>(object: &'obj mut Object, name: &str) -> MapMut<'obj> { | ||
object | ||
.maps_mut() | ||
.find(|map| map.name() == name) | ||
.unwrap_or_else(|| panic!("failed to find map `{name}`")) | ||
} | ||
|
||
/// Find the BPF program with the given name, panic if it does not exist. | ||
#[track_caller] | ||
pub fn prog_mut<'obj>(object: &'obj mut Object, name: &str) -> ProgramMut<'obj> { | ||
object | ||
.progs_mut() | ||
.find(|map| map.name() == name) | ||
.unwrap_or_else(|| panic!("failed to find program `{name}`")) | ||
} | ||
|
||
/// A helper function for instantiating a `RingBuffer` with a callback meant | ||
/// to be invoked when `action` is executed and that is intended to | ||
/// trigger a write to said `RingBuffer` from kernel space, which then | ||
/// reads a single `u32` from this buffer from user space and returns | ||
/// it. | ||
fn with_ringbuffer<F>(map: &Map, action: F) -> Vec<u8> | ||
where | ||
F: FnOnce(), | ||
{ | ||
let mut value = None; | ||
{ | ||
let callback = |data: &[u8]| { | ||
value = Some(data.to_vec()); | ||
0 | ||
}; | ||
|
||
let mut builder = RingBufferBuilder::new(); | ||
builder.add(map, callback).expect("failed to add ringbuf"); | ||
let ringbuf = builder.build().expect("failed to build"); | ||
|
||
let () = action(); | ||
let () = ringbuf.consume().expect("failed to consume ringbuf"); | ||
} | ||
|
||
value.expect("did not receive RingBuffer callback") | ||
} | ||
|
||
/// Retrieve the address of the `handle__getpid` and `subprogram` | ||
/// functions in the `getpid.bpf.o` BPF program. | ||
pub fn with_bpf_symbolization_target_addrs<F>(f: F) | ||
where | ||
F: FnOnce(Addr, Addr), | ||
{ | ||
let mut obj = test_object("getpid.bpf.o"); | ||
let prog = prog_mut(&mut obj, "handle__getpid"); | ||
let _link = prog | ||
.attach_tracepoint("syscalls", "sys_enter_getpid") | ||
.expect("failed to attach prog"); | ||
|
||
let map = map_mut(&mut obj, "ringbuf"); | ||
let action = || { | ||
let _pid = unsafe { libc::getpid() }; | ||
}; | ||
let data = with_ringbuffer(&map, action); | ||
let mut data = data.as_slice(); | ||
let handle_getpid = data.read_pod::<Addr>().unwrap(); | ||
let subprogram = data.read_pod::<Addr>().unwrap(); | ||
f(handle_getpid, subprogram) | ||
} | ||
} | ||
|
||
#[cfg(linux)] | ||
pub use bpf::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.