Skip to content

Commit 52ab250

Browse files
d-e-s-oinsearchoflosttime
authored andcommitted
libbpf-rs: Add BPF linker support
A while back libbpf got support for linking multiple BPF object files statically into a single one [0]. This functionality is useful in and off itself and should be exposed as such by this library, but it is also a suitable building block for ensuring deterministic skeleton creation [1] [2] [3]. As such, this change hooks it up. We mirror the libbpf APIs very closely, just packaging them up in a nicer Rust interface. [0] https://lwn.net/ml/bpf/20210310040431.916483-6-andrii@kernel.org/ [1] #177 [2] #163 [3] #169 Signed-off-by: Daniel Müller <deso@posteo.net>
1 parent 450a5db commit 52ab250

File tree

5 files changed

+210
-38
lines changed

5 files changed

+210
-38
lines changed

Cargo.lock

Lines changed: 77 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libbpf-rs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ plain = "0.2.3"
3737
probe = "0.3"
3838
scopeguard = "1.1"
3939
serial_test = "0.5"
40+
tempfile = "3.3"
4041

4142
# A set of unused dependencies that we require to force correct minimum versions
4243
# of transitive dependencies, for cases where our dependencies have incorrect

libbpf-rs/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
mod error;
7676
mod iter;
7777
mod link;
78+
mod linker;
7879
mod map;
7980
mod object;
8081
mod perf_buffer;
@@ -93,6 +94,7 @@ pub use libbpf_sys;
9394
pub use crate::error::{Error, Result};
9495
pub use crate::iter::Iter;
9596
pub use crate::link::Link;
97+
pub use crate::linker::Linker;
9698
pub use crate::map::{Map, MapFlags, MapType, OpenMap};
9799
pub use crate::object::{Object, ObjectBuilder, OpenObject};
98100
pub use crate::perf_buffer::{PerfBuffer, PerfBufferBuilder};

libbpf-rs/src/linker.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::path::Path;
2+
use std::ptr::null_mut;
3+
4+
use crate::util::path_to_cstring;
5+
use crate::Error;
6+
use crate::Result;
7+
8+
/// A type used for linking multiple BPF object files into a single one.
9+
///
10+
/// Please refer to
11+
/// <https://lwn.net/ml/bpf/20210310040431.916483-6-andrii@kernel.org/> for
12+
/// additional details.
13+
#[derive(Debug)]
14+
pub struct Linker {
15+
/// The `libbpf` linker object.
16+
linker: *mut libbpf_sys::bpf_linker,
17+
}
18+
19+
impl Linker {
20+
/// Instantiate a `Linker` object.
21+
pub fn new<P>(output: P) -> Result<Self>
22+
where
23+
P: AsRef<Path>,
24+
{
25+
let output = path_to_cstring(output)?;
26+
let opts = null_mut();
27+
// SAFETY: `output` is a valid pointer and `opts` is accepted as NULL.
28+
let linker = unsafe { libbpf_sys::bpf_linker__new(output.as_ptr(), opts) };
29+
// SAFETY: `libbpf_get_error` is always safe to call.
30+
let err = unsafe { libbpf_sys::libbpf_get_error(linker as *const _) };
31+
if err != 0 {
32+
return Err(Error::System(err as i32));
33+
}
34+
35+
let slf = Self { linker };
36+
Ok(slf)
37+
}
38+
39+
/// Add a file to the set of files to link.
40+
pub fn add<P>(&mut self, file: P) -> Result<()>
41+
where
42+
P: AsRef<Path>,
43+
{
44+
let file = path_to_cstring(file)?;
45+
let opts = null_mut();
46+
// SAFETY: `linker` and `file` are a valid pointers.
47+
let err = unsafe { libbpf_sys::bpf_linker__add_file(self.linker, file.as_ptr(), opts) };
48+
if err != 0 {
49+
Err(Error::System(err))
50+
} else {
51+
Ok(())
52+
}
53+
}
54+
55+
/// Link all BPF object files [`add`](Self::add)ed to this object into a single one.
56+
pub fn link(&self) -> Result<()> {
57+
// SAFETY: `linker` is a valid pointer.
58+
let err = unsafe { libbpf_sys::bpf_linker__finalize(self.linker) };
59+
if err != 0 {
60+
return Err(Error::System(err));
61+
}
62+
Ok(())
63+
}
64+
}
65+
66+
// SAFETY: `bpf_linker` can be sent to a different thread.
67+
unsafe impl Send for Linker {}
68+
69+
impl Drop for Linker {
70+
fn drop(&mut self) {
71+
// SAFETY: `linker` is a valid pointer returned by `bpf_linker__new`.
72+
unsafe { libbpf_sys::bpf_linker__free(self.linker) }
73+
}
74+
}
75+
76+
#[cfg(test)]
77+
mod test {
78+
use super::*;
79+
80+
/// Check that `Linker` is `Send`.
81+
#[test]
82+
fn linker_is_send() {
83+
fn test<T>()
84+
where
85+
T: Send,
86+
{
87+
}
88+
89+
test::<Linker>();
90+
}
91+
}

0 commit comments

Comments
 (0)