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
299impl AsRawLibbpf for OpenObject {
300 type LibbpfType = libbpf_sys::bpf_object;
301
302 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
304 self.ptr
305 }
306}
307
308impl Drop for OpenObject {
309 fn drop(&mut self) {
310 unsafe {
312 libbpf_sys::bpf_object__close(self.ptr.as_ptr());
313 }
314 }
315}
316
317#[derive(Debug)]
327#[repr(transparent)]
328pub struct Object {
329 ptr: NonNull<libbpf_sys::bpf_object>,
330}
331
332impl Object {
333 pub unsafe fn from_ptr(ptr: NonNull<libbpf_sys::bpf_object>) -> Self {
342 Self { ptr }
343 }
344
345 pub fn name(&self) -> Option<&OsStr> {
347 let name_ptr = unsafe { libbpf_sys::bpf_object__name(self.ptr.as_ptr()) };
349 let err = unsafe { libbpf_sys::libbpf_get_error(name_ptr as *const _) };
351 if err != 0 {
352 return None
353 }
354 let name_c_str = unsafe { CStr::from_ptr(name_ptr) };
355 let str = OsStr::from_bytes(name_c_str.to_bytes());
356 Some(str)
357 }
358
359 pub fn btf(&self) -> Result<Option<Btf<'_>>> {
361 Btf::from_bpf_object(unsafe { &*self.ptr.as_ptr() })
362 }
363
364 pub fn maps(&self) -> impl Iterator<Item = Map<'_>> {
366 MapIter::new(unsafe { self.ptr.as_ref() })
367 .filter(|ptr| map_fd(*ptr).is_some())
368 .map(|ptr| unsafe { Map::new(ptr.as_ref()) })
369 }
370
371 pub fn maps_mut(&mut self) -> impl Iterator<Item = MapMut<'_>> {
373 MapIter::new(unsafe { self.ptr.as_ref() })
374 .filter(|ptr| map_fd(*ptr).is_some())
375 .map(|mut ptr| unsafe { MapMut::new_mut(ptr.as_mut()) })
376 }
377
378 pub fn progs(&self) -> impl Iterator<Item = Program<'_>> {
380 ProgIter::new(unsafe { self.ptr.as_ref() }).map(|ptr| unsafe { Program::new(ptr.as_ref()) })
381 }
382
383 pub fn progs_mut(&self) -> impl Iterator<Item = ProgramMut<'_>> {
385 ProgIter::new(unsafe { self.ptr.as_ref() })
386 .map(|mut ptr| unsafe { ProgramMut::new_mut(ptr.as_mut()) })
387 }
388}
389
390impl AsRawLibbpf for Object {
391 type LibbpfType = libbpf_sys::bpf_object;
392
393 fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
395 self.ptr
396 }
397}
398
399impl Drop for Object {
400 fn drop(&mut self) {
401 unsafe {
402 libbpf_sys::bpf_object__close(self.ptr.as_ptr());
403 }
404 }
405}