1use core::ffi::c_void;
2use std::ffi::CStr;
3use std::ffi::CString;
4use std::ffi::OsStr;
5use std::mem;
6use std::os::unix::ffi::OsStrExt as _;
7use std::path::Path;
8use std::ptr;
9use std::ptr::addr_of;
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
110 opts: libbpf_sys::bpf_object_open_opts,
111}
112
113impl Default for ObjectBuilder {
114 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 };
127 Self {
128 name: None,
129 pin_root_path: None,
130 opts,
131 }
132 }
133}
134
135impl ObjectBuilder {
136 pub fn name<T: AsRef<str>>(&mut self, name: T) -> Result<&mut Self> {
138 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());
140 Ok(self)
141 }
142
143 pub fn pin_root_path<T: AsRef<Path>>(&mut self, path: T) -> Result<&mut Self> {
147 self.pin_root_path = Some(util::path_to_cstring(path)?);
148 self.opts.pin_root_path = self
149 .pin_root_path
150 .as_ref()
151 .map_or(ptr::null(), |p| p.as_ptr());
152 Ok(self)
153 }
154
155 pub fn relaxed_maps(&mut self, relaxed_maps: bool) -> &mut Self {
157 self.opts.relaxed_maps = relaxed_maps;
158 self
159 }
160
161 pub fn debug(&mut self, dbg: bool) -> &mut Self {
166 if dbg {
167 set_print(Some((PrintLevel::Debug, |_, s| print!("{s}"))));
168 } else {
169 set_print(None);
170 }
171 self
172 }
173
174 pub fn open_file<P: AsRef<Path>>(&mut self, path: P) -> Result<OpenObject> {
176 let path = path.as_ref();
177 let path_c = util::path_to_cstring(path)?;
178 let path_ptr = path_c.as_ptr();
179 let opts_ptr = self.as_libbpf_object().as_ptr();
180
181 let ptr = unsafe { libbpf_sys::bpf_object__open_file(path_ptr, opts_ptr) };
182 let ptr = validate_bpf_ret(ptr)
183 .with_context(|| format!("failed to open object from `{}`", path.display()))?;
184
185 let obj = unsafe { OpenObject::from_ptr(ptr) };
186 Ok(obj)
187 }
188
189 pub fn open_memory(&mut self, mem: &[u8]) -> Result<OpenObject> {
191 let opts_ptr = self.as_libbpf_object().as_ptr();
192 let ptr = unsafe {
193 libbpf_sys::bpf_object__open_mem(
194 mem.as_ptr() as *const c_void,
195 mem.len() as libbpf_sys::size_t,
196 opts_ptr,
197 )
198 };
199 let ptr = validate_bpf_ret(ptr).context("failed to open object from memory")?;
200 let obj = unsafe { OpenObject::from_ptr(ptr) };
201 Ok(obj)
202 }
203}
204
205impl AsRawLibbpf for ObjectBuilder {
206 type LibbpfType = libbpf_sys::bpf_object_open_opts;
207
208 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
210 unsafe { NonNull::new_unchecked(addr_of!(self.opts).cast_mut()) }
212 }
213}
214
215
216#[derive(Debug)]
220#[repr(transparent)]
221pub struct OpenObject {
222 ptr: NonNull<libbpf_sys::bpf_object>,
223}
224
225impl OpenObject {
226 pub unsafe fn from_ptr(ptr: NonNull<libbpf_sys::bpf_object>) -> Self {
237 Self { ptr }
238 }
239
240 pub fn take_ptr(mut self) -> NonNull<libbpf_sys::bpf_object> {
242 let ptr = {
243 let Self { ptr } = &mut self;
244 *ptr
245 };
246 mem::forget(self);
248 ptr
249 }
250
251 pub fn name(&self) -> Option<&OsStr> {
253 let name_ptr = unsafe { libbpf_sys::bpf_object__name(self.ptr.as_ptr()) };
255 let err = unsafe { libbpf_sys::libbpf_get_error(name_ptr as *const _) };
257 if err != 0 {
258 return None
259 }
260 let name_c_str = unsafe { CStr::from_ptr(name_ptr) };
261 let str = OsStr::from_bytes(name_c_str.to_bytes());
262 Some(str)
263 }
264
265 pub fn maps(&self) -> impl Iterator<Item = OpenMap<'_>> {
267 MapIter::new(unsafe { self.ptr.as_ref() }).map(|ptr| unsafe { OpenMap::new(ptr.as_ref()) })
268 }
269
270 pub fn maps_mut(&mut self) -> impl Iterator<Item = OpenMapMut<'_>> {
272 MapIter::new(unsafe { self.ptr.as_ref() })
273 .map(|mut ptr| unsafe { OpenMapMut::new_mut(ptr.as_mut()) })
274 }
275
276 pub fn progs(&self) -> impl Iterator<Item = OpenProgram<'_>> {
278 ProgIter::new(unsafe { self.ptr.as_ref() })
279 .map(|ptr| unsafe { OpenProgram::new(ptr.as_ref()) })
280 }
281
282 pub fn progs_mut(&mut self) -> impl Iterator<Item = OpenProgramMut<'_>> {
284 ProgIter::new(unsafe { self.ptr.as_ref() })
285 .map(|mut ptr| unsafe { OpenProgramMut::new_mut(ptr.as_mut()) })
286 }
287
288 pub fn load(self) -> Result<Object> {
290 let ret = unsafe { libbpf_sys::bpf_object__load(self.ptr.as_ptr()) };
291 let () = util::parse_ret(ret)?;
292
293 let obj = unsafe { Object::from_ptr(self.take_ptr()) };
294
295 Ok(obj)
296 }
297}
298
299unsafe impl Send for OpenObject {}
301unsafe impl Sync for OpenObject {}
303
304impl AsRawLibbpf for OpenObject {
305 type LibbpfType = libbpf_sys::bpf_object;
306
307 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
309 self.ptr
310 }
311}
312
313impl Drop for OpenObject {
314 fn drop(&mut self) {
315 unsafe {
317 libbpf_sys::bpf_object__close(self.ptr.as_ptr());
318 }
319 }
320}
321
322
323#[derive(Debug)]
333#[repr(transparent)]
334pub struct Object {
335 ptr: NonNull<libbpf_sys::bpf_object>,
336}
337
338impl Object {
339 pub unsafe fn from_ptr(ptr: NonNull<libbpf_sys::bpf_object>) -> Self {
348 Self { ptr }
349 }
350
351 pub fn name(&self) -> Option<&OsStr> {
353 let name_ptr = unsafe { libbpf_sys::bpf_object__name(self.ptr.as_ptr()) };
355 let err = unsafe { libbpf_sys::libbpf_get_error(name_ptr as *const _) };
357 if err != 0 {
358 return None
359 }
360 let name_c_str = unsafe { CStr::from_ptr(name_ptr) };
361 let str = OsStr::from_bytes(name_c_str.to_bytes());
362 Some(str)
363 }
364
365 pub fn btf(&self) -> Result<Option<Btf<'_>>> {
367 Btf::from_bpf_object(unsafe { &*self.ptr.as_ptr() })
368 }
369
370 pub fn maps(&self) -> impl Iterator<Item = Map<'_>> {
372 MapIter::new(unsafe { self.ptr.as_ref() })
373 .filter(|ptr| map_fd(*ptr).is_some())
374 .map(|ptr| unsafe { Map::new(ptr.as_ref()) })
375 }
376
377 pub fn maps_mut(&mut self) -> impl Iterator<Item = MapMut<'_>> {
379 MapIter::new(unsafe { self.ptr.as_ref() })
380 .filter(|ptr| map_fd(*ptr).is_some())
381 .map(|mut ptr| unsafe { MapMut::new_mut(ptr.as_mut()) })
382 }
383
384 pub fn progs(&self) -> impl Iterator<Item = Program<'_>> {
386 ProgIter::new(unsafe { self.ptr.as_ref() }).map(|ptr| unsafe { Program::new(ptr.as_ref()) })
387 }
388
389 pub fn progs_mut(&self) -> impl Iterator<Item = ProgramMut<'_>> {
391 ProgIter::new(unsafe { self.ptr.as_ref() })
392 .map(|mut ptr| unsafe { ProgramMut::new_mut(ptr.as_mut()) })
393 }
394}
395
396unsafe impl Send for Object {}
398unsafe impl Sync for Object {}
400
401impl AsRawLibbpf for Object {
402 type LibbpfType = libbpf_sys::bpf_object;
403
404 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
406 self.ptr
407 }
408}
409
410impl Drop for Object {
411 fn drop(&mut self) {
412 unsafe {
413 libbpf_sys::bpf_object__close(self.ptr.as_ptr());
414 }
415 }
416}