1use core::ffi::c_void;
2use std::cell::OnceCell;
3use std::ffi::CStr;
4use std::ffi::CString;
5use std::ffi::OsStr;
6use std::mem;
7use std::os::unix::ffi::OsStrExt as _;
8use std::path::Path;
9use std::ptr;
10use std::ptr::NonNull;
11
12use crate::map::map_fd;
13use crate::set_print;
14use crate::util;
15use crate::util::validate_bpf_ret;
16use crate::Btf;
17use crate::ErrorExt as _;
18use crate::Map;
19use crate::MapMut;
20use crate::OpenMap;
21use crate::OpenMapMut;
22use crate::OpenProgram;
23use crate::OpenProgramMut;
24use crate::PrintLevel;
25use crate::Program;
26use crate::ProgramMut;
27use crate::Result;
28
29
30#[derive(Debug)]
32pub struct MapIter<'obj> {
33 obj: &'obj libbpf_sys::bpf_object,
34 last: *mut libbpf_sys::bpf_map,
35}
36
37impl<'obj> MapIter<'obj> {
38 pub fn new(obj: &'obj libbpf_sys::bpf_object) -> Self {
40 Self {
41 obj,
42 last: ptr::null_mut(),
43 }
44 }
45}
46
47impl Iterator for MapIter<'_> {
48 type Item = NonNull<libbpf_sys::bpf_map>;
49
50 fn next(&mut self) -> Option<Self::Item> {
51 self.last = unsafe { libbpf_sys::bpf_object__next_map(self.obj, self.last) };
52 NonNull::new(self.last)
53 }
54}
55
56
57#[derive(Debug)]
59pub struct ProgIter<'obj> {
60 obj: &'obj libbpf_sys::bpf_object,
61 last: *mut libbpf_sys::bpf_program,
62}
63
64impl<'obj> ProgIter<'obj> {
65 pub fn new(obj: &'obj libbpf_sys::bpf_object) -> Self {
67 Self {
68 obj,
69 last: ptr::null_mut(),
70 }
71 }
72}
73
74impl Iterator for ProgIter<'_> {
75 type Item = NonNull<libbpf_sys::bpf_program>;
76
77 fn next(&mut self) -> Option<Self::Item> {
78 self.last = unsafe { libbpf_sys::bpf_object__next_program(self.obj, self.last) };
79 NonNull::new(self.last)
80 }
81}
82
83
84pub trait AsRawLibbpf {
90 type LibbpfType;
92
93 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType>;
102}
103
104#[derive(Debug)]
106pub struct ObjectBuilder {
107 name: Option<CString>,
108 pin_root_path: Option<CString>,
109 btf_custom_path: Option<CString>,
110
111 opts: OnceCell<libbpf_sys::bpf_object_open_opts>,
112}
113
114impl Default for ObjectBuilder {
115 fn default() -> Self {
116 Self {
117 name: None,
118 pin_root_path: None,
119 btf_custom_path: None,
120 opts: OnceCell::new(),
121 }
122 }
123}
124
125impl PartialEq for ObjectBuilder {
126 fn eq(&self, other: &Self) -> bool {
127 let Self {
128 name,
129 pin_root_path,
130 btf_custom_path,
131 opts,
132 } = self;
133
134 opts.get().is_none()
138 && other.opts.get().is_none()
139 && name == &other.name
140 && pin_root_path == &other.pin_root_path
141 && btf_custom_path == &other.btf_custom_path
142 }
143}
144
145impl ObjectBuilder {
146 fn opts(&self) -> &libbpf_sys::bpf_object_open_opts {
147 self.opts.get_or_init(|| libbpf_sys::bpf_object_open_opts {
148 sz: mem::size_of::<libbpf_sys::bpf_object_open_opts>() as libbpf_sys::size_t,
149 ..Default::default()
150 })
151 }
152
153 fn opts_mut(&mut self) -> &mut libbpf_sys::bpf_object_open_opts {
154 let _opts = self.opts();
155 self.opts.get_mut().unwrap()
157 }
158
159 pub fn name<T: AsRef<str>>(&mut self, name: T) -> Result<&mut Self> {
161 self.name = Some(util::str_to_cstring(name.as_ref())?);
162 self.opts_mut().object_name = self.name.as_ref().map_or(ptr::null(), |p| p.as_ptr());
163 Ok(self)
164 }
165
166 pub fn pin_root_path<T: AsRef<Path>>(&mut self, path: T) -> Result<&mut Self> {
170 self.pin_root_path = Some(util::path_to_cstring(path)?);
171 self.opts_mut().pin_root_path = self
172 .pin_root_path
173 .as_ref()
174 .map_or(ptr::null(), |p| p.as_ptr());
175 Ok(self)
176 }
177
178 pub fn btf_custom_path<T: AsRef<Path>>(&mut self, path: T) -> Result<&mut Self> {
183 self.btf_custom_path = Some(util::path_to_cstring(path)?);
184 self.opts_mut().btf_custom_path = self
185 .btf_custom_path
186 .as_ref()
187 .map_or(ptr::null(), |p| p.as_ptr());
188 Ok(self)
189 }
190
191 pub fn relaxed_maps(&mut self, relaxed_maps: bool) -> &mut Self {
193 self.opts_mut().relaxed_maps = relaxed_maps;
194 self
195 }
196
197 pub fn debug(&mut self, dbg: bool) -> &mut Self {
202 if dbg {
203 set_print(Some((PrintLevel::Debug, |_, s| print!("{s}"))));
204 } else {
205 set_print(None);
206 }
207 self
208 }
209
210 pub fn open_file<P: AsRef<Path>>(&mut self, path: P) -> Result<OpenObject> {
212 let path = path.as_ref();
213 let path_c = util::path_to_cstring(path)?;
214 let path_ptr = path_c.as_ptr();
215 let opts_ptr = self.as_libbpf_object().as_ptr();
216
217 let ptr = unsafe { libbpf_sys::bpf_object__open_file(path_ptr, opts_ptr) };
218 let ptr = validate_bpf_ret(ptr)
219 .with_context(|| format!("failed to open object from `{}`", path.display()))?;
220
221 let obj = unsafe { OpenObject::from_ptr(ptr) };
222 Ok(obj)
223 }
224
225 pub fn open_memory(&mut self, mem: &[u8]) -> Result<OpenObject> {
227 let opts_ptr = self.as_libbpf_object().as_ptr();
228 let ptr = unsafe {
229 libbpf_sys::bpf_object__open_mem(
230 mem.as_ptr() as *const c_void,
231 mem.len() as libbpf_sys::size_t,
232 opts_ptr,
233 )
234 };
235 let ptr = validate_bpf_ret(ptr).context("failed to open object from memory")?;
236 let obj = unsafe { OpenObject::from_ptr(ptr) };
237 Ok(obj)
238 }
239}
240
241impl AsRawLibbpf for ObjectBuilder {
242 type LibbpfType = libbpf_sys::bpf_object_open_opts;
243
244 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
246 unsafe { NonNull::new_unchecked(ptr::from_ref(self.opts()).cast_mut()) }
248 }
249}
250
251
252#[derive(Debug)]
256#[repr(transparent)]
257pub struct OpenObject {
258 ptr: NonNull<libbpf_sys::bpf_object>,
259}
260
261impl OpenObject {
262 pub unsafe fn from_ptr(ptr: NonNull<libbpf_sys::bpf_object>) -> Self {
273 Self { ptr }
274 }
275
276 pub fn take_ptr(mut self) -> NonNull<libbpf_sys::bpf_object> {
278 let ptr = {
279 let Self { ptr } = &mut self;
280 *ptr
281 };
282 mem::forget(self);
284 ptr
285 }
286
287 pub fn name(&self) -> Option<&OsStr> {
289 let name_ptr = unsafe { libbpf_sys::bpf_object__name(self.ptr.as_ptr()) };
291 let err = unsafe { libbpf_sys::libbpf_get_error(name_ptr as *const _) };
293 if err != 0 {
294 return None
295 }
296 let name_c_str = unsafe { CStr::from_ptr(name_ptr) };
297 let str = OsStr::from_bytes(name_c_str.to_bytes());
298 Some(str)
299 }
300
301 pub fn maps(&self) -> impl Iterator<Item = OpenMap<'_>> {
303 MapIter::new(unsafe { self.ptr.as_ref() }).map(|ptr| unsafe { OpenMap::new(ptr.as_ref()) })
304 }
305
306 pub fn maps_mut(&mut self) -> impl Iterator<Item = OpenMapMut<'_>> {
308 MapIter::new(unsafe { self.ptr.as_ref() })
309 .map(|mut ptr| unsafe { OpenMapMut::new_mut(ptr.as_mut()) })
310 }
311
312 pub fn progs(&self) -> impl Iterator<Item = OpenProgram<'_>> {
314 ProgIter::new(unsafe { self.ptr.as_ref() })
315 .map(|ptr| unsafe { OpenProgram::new(ptr.as_ref()) })
316 }
317
318 pub fn progs_mut(&mut self) -> impl Iterator<Item = OpenProgramMut<'_>> {
320 ProgIter::new(unsafe { self.ptr.as_ref() })
321 .map(|mut ptr| unsafe { OpenProgramMut::new_mut(ptr.as_mut()) })
322 }
323
324 pub fn load(self) -> Result<Object> {
326 let ret = unsafe { libbpf_sys::bpf_object__load(self.ptr.as_ptr()) };
327 let () = util::parse_ret(ret)?;
328
329 let obj = unsafe { Object::from_ptr(self.take_ptr()) };
330
331 Ok(obj)
332 }
333}
334
335unsafe impl Send for OpenObject {}
337unsafe impl Sync for OpenObject {}
339
340impl AsRawLibbpf for OpenObject {
341 type LibbpfType = libbpf_sys::bpf_object;
342
343 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
345 self.ptr
346 }
347}
348
349impl Drop for OpenObject {
350 fn drop(&mut self) {
351 unsafe {
353 libbpf_sys::bpf_object__close(self.ptr.as_ptr());
354 }
355 }
356}
357
358
359#[derive(Debug)]
369#[repr(transparent)]
370pub struct Object {
371 ptr: NonNull<libbpf_sys::bpf_object>,
372}
373
374impl Object {
375 pub unsafe fn from_ptr(ptr: NonNull<libbpf_sys::bpf_object>) -> Self {
384 Self { ptr }
385 }
386
387 pub fn name(&self) -> Option<&OsStr> {
389 let name_ptr = unsafe { libbpf_sys::bpf_object__name(self.ptr.as_ptr()) };
391 let err = unsafe { libbpf_sys::libbpf_get_error(name_ptr as *const _) };
393 if err != 0 {
394 return None
395 }
396 let name_c_str = unsafe { CStr::from_ptr(name_ptr) };
397 let str = OsStr::from_bytes(name_c_str.to_bytes());
398 Some(str)
399 }
400
401 pub fn btf(&self) -> Result<Option<Btf<'_>>> {
403 Btf::from_bpf_object(unsafe { &*self.ptr.as_ptr() })
404 }
405
406 pub fn maps(&self) -> impl Iterator<Item = Map<'_>> {
408 MapIter::new(unsafe { self.ptr.as_ref() })
409 .filter(|ptr| map_fd(*ptr).is_some())
410 .map(|ptr| unsafe { Map::new(ptr.as_ref()) })
411 }
412
413 pub fn maps_mut(&mut self) -> impl Iterator<Item = MapMut<'_>> {
415 MapIter::new(unsafe { self.ptr.as_ref() })
416 .filter(|ptr| map_fd(*ptr).is_some())
417 .map(|mut ptr| unsafe { MapMut::new_mut(ptr.as_mut()) })
418 }
419
420 pub fn progs(&self) -> impl Iterator<Item = Program<'_>> {
422 ProgIter::new(unsafe { self.ptr.as_ref() }).map(|ptr| unsafe { Program::new(ptr.as_ref()) })
423 }
424
425 pub fn progs_mut(&self) -> impl Iterator<Item = ProgramMut<'_>> {
427 ProgIter::new(unsafe { self.ptr.as_ref() })
428 .map(|mut ptr| unsafe { ProgramMut::new_mut(ptr.as_mut()) })
429 }
430}
431
432unsafe impl Send for Object {}
434unsafe impl Sync for Object {}
436
437impl AsRawLibbpf for Object {
438 type LibbpfType = libbpf_sys::bpf_object;
439
440 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
442 self.ptr
443 }
444}
445
446impl Drop for Object {
447 fn drop(&mut self) {
448 unsafe {
449 libbpf_sys::bpf_object__close(self.ptr.as_ptr());
450 }
451 }
452}