Skip to content

Commit 52e1c51

Browse files
committed
libbpf-cargo: Honor ObjectBuilder in skeleton infrastructure
With commit d105bf2 ("libbpf-cargo: Open skeleton without options by default") we changed the default behavior of the generated SkelBuilder to only use open options if explicitly provided to the newly added open_opts() constructor. What wasn't handled correctly was the existing options present in the obj_builder member. Fix this by trying to be more clever and auto detect whether the ObjectBuilder has had any changes over its default representation. Closes: libbpf#1309 Reported-by: Francisco Javier Honduvilla Coto <[email protected]> Signed-off-by: Daniel Müller <[email protected]>
1 parent 9622223 commit 52e1c51

File tree

3 files changed

+50
-20
lines changed

3 files changed

+50
-20
lines changed

libbpf-cargo/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Unreleased
22
----------
33
- Fixed Rust type generation for trailing bitfields in composite C types
4+
- Fixed handling of `XxxSkelBuilder::obj_builder` customizations when
5+
using `open()` constructor
46
- Allowlisted `libbpf-sys` `1.6.2`
57

68

libbpf-cargo/src/gen/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ fn gen_skel_contents(raw_obj_name: &str, obj_file_path: &Path) -> Result<String>
860860
use libbpf_rs::skel::SkelBuilder;
861861
use libbpf_rs::AsRawLibbpf as _;
862862
use libbpf_rs::MapCore as _;
863+
use libbpf_rs::ObjectBuilder;
863864
"
864865
)?;
865866

@@ -983,7 +984,15 @@ fn gen_skel_contents(raw_obj_name: &str, obj_file_path: &Path) -> Result<String>
983984
self,
984985
object: &'obj mut std::mem::MaybeUninit<libbpf_rs::OpenObject>,
985986
) -> libbpf_rs::Result<Open{name}Skel<'obj>> {{
986-
self.open_opts_impl(std::ptr::null(), object)
987+
// Only produce a pointer to our custom open opts object
988+
// if customizations have been made. This works around a
989+
// bug in older versions of libbpf.
990+
let opts = if self.obj_builder.ne(&ObjectBuilder::default()) {{
991+
self.obj_builder.as_libbpf_object().as_ptr().cast_const()
992+
}} else {{
993+
std::ptr::null()
994+
}};
995+
self.open_opts_impl(opts, object)
987996
}}
988997
989998
fn open_opts(

libbpf-rs/src/object.rs

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use core::ffi::c_void;
2+
use std::cell::OnceCell;
23
use std::ffi::CStr;
34
use std::ffi::CString;
45
use std::ffi::OsStr;
56
use std::mem;
67
use std::os::unix::ffi::OsStrExt as _;
78
use std::path::Path;
89
use std::ptr;
9-
use std::ptr::addr_of;
1010
use std::ptr::NonNull;
1111

1212
use crate::map::map_fd;
@@ -107,36 +107,55 @@ pub struct ObjectBuilder {
107107
name: Option<CString>,
108108
pin_root_path: Option<CString>,
109109

110-
opts: libbpf_sys::bpf_object_open_opts,
110+
opts: OnceCell<libbpf_sys::bpf_object_open_opts>,
111111
}
112112

113113
impl Default for ObjectBuilder {
114114
fn default() -> Self {
115-
let opts = libbpf_sys::bpf_object_open_opts {
116-
sz: mem::size_of::<libbpf_sys::bpf_object_open_opts>() as libbpf_sys::size_t,
117-
object_name: ptr::null(),
118-
relaxed_maps: false,
119-
pin_root_path: ptr::null(),
120-
kconfig: ptr::null(),
121-
btf_custom_path: ptr::null(),
122-
kernel_log_buf: ptr::null_mut(),
123-
kernel_log_size: 0,
124-
kernel_log_level: 0,
125-
..Default::default()
126-
};
127115
Self {
128116
name: None,
129117
pin_root_path: None,
130-
opts,
118+
opts: OnceCell::new(),
131119
}
132120
}
133121
}
134122

123+
impl PartialEq for ObjectBuilder {
124+
fn eq(&self, other: &Self) -> bool {
125+
let Self {
126+
name,
127+
pin_root_path,
128+
opts,
129+
} = self;
130+
131+
// `bpf_object_open_opts` doesn't implement `PartialEq` and we
132+
// don't want to manually compare fields. Just render our
133+
// objects "uncomparable" if it is present.
134+
opts.get().is_none()
135+
&& other.opts.get().is_none()
136+
&& name == &other.name
137+
&& pin_root_path == &other.pin_root_path
138+
}
139+
}
140+
135141
impl ObjectBuilder {
142+
fn opts(&self) -> &libbpf_sys::bpf_object_open_opts {
143+
self.opts.get_or_init(|| libbpf_sys::bpf_object_open_opts {
144+
sz: mem::size_of::<libbpf_sys::bpf_object_open_opts>() as libbpf_sys::size_t,
145+
..Default::default()
146+
})
147+
}
148+
149+
fn opts_mut(&mut self) -> &mut libbpf_sys::bpf_object_open_opts {
150+
let _opts = self.opts();
151+
// SANITY: We just made sure to initialize the object above.
152+
self.opts.get_mut().unwrap()
153+
}
154+
136155
/// Override the generated name that would have been inferred from the constructor.
137156
pub fn name<T: AsRef<str>>(&mut self, name: T) -> Result<&mut Self> {
138157
self.name = Some(util::str_to_cstring(name.as_ref())?);
139-
self.opts.object_name = self.name.as_ref().map_or(ptr::null(), |p| p.as_ptr());
158+
self.opts_mut().object_name = self.name.as_ref().map_or(ptr::null(), |p| p.as_ptr());
140159
Ok(self)
141160
}
142161

@@ -145,7 +164,7 @@ impl ObjectBuilder {
145164
/// By default, this is NULL which bpf translates to /sys/fs/bpf
146165
pub fn pin_root_path<T: AsRef<Path>>(&mut self, path: T) -> Result<&mut Self> {
147166
self.pin_root_path = Some(util::path_to_cstring(path)?);
148-
self.opts.pin_root_path = self
167+
self.opts_mut().pin_root_path = self
149168
.pin_root_path
150169
.as_ref()
151170
.map_or(ptr::null(), |p| p.as_ptr());
@@ -154,7 +173,7 @@ impl ObjectBuilder {
154173

155174
/// Option to parse map definitions non-strictly, allowing extra attributes/data
156175
pub fn relaxed_maps(&mut self, relaxed_maps: bool) -> &mut Self {
157-
self.opts.relaxed_maps = relaxed_maps;
176+
self.opts_mut().relaxed_maps = relaxed_maps;
158177
self
159178
}
160179

@@ -208,7 +227,7 @@ impl AsRawLibbpf for ObjectBuilder {
208227
/// Retrieve the underlying [`libbpf_sys::bpf_object_open_opts`].
209228
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
210229
// SAFETY: A reference is always a valid pointer.
211-
unsafe { NonNull::new_unchecked(addr_of!(self.opts).cast_mut()) }
230+
unsafe { NonNull::new_unchecked(ptr::from_ref(self.opts()).cast_mut()) }
212231
}
213232
}
214233

0 commit comments

Comments
 (0)