1use std::ffi::c_void;
14use std::ffi::CStr;
15use std::ffi::CString;
16use std::io;
17use std::mem::size_of_val;
18use std::mem::zeroed;
19use std::os::fd::AsFd;
20use std::os::fd::AsRawFd;
21use std::os::fd::BorrowedFd;
22use std::os::fd::FromRawFd;
23use std::os::fd::OwnedFd;
24use std::os::raw::c_char;
25use std::ptr;
26use std::time::Duration;
27
28use crate::util;
29use crate::MapType;
30use crate::ProgramAttachType;
31use crate::ProgramType;
32use crate::Result;
33
34macro_rules! gen_info_impl {
35 ($(#[$attr:meta])*
37 $name:ident, $info_ty:ty, $uapi_info_ty:ty, $next_id:expr, $fd_by_id:expr) => {
38 $(#[$attr])*
39 #[derive(Default, Debug)]
40 pub struct $name {
41 cur_id: u32,
42 }
43
44 impl $name {
45 fn next_valid_fd(&mut self) -> Option<OwnedFd> {
47 loop {
48 if unsafe { $next_id(self.cur_id, &mut self.cur_id) } != 0 {
49 return None;
50 }
51
52 let fd = unsafe { $fd_by_id(self.cur_id) };
53 if fd < 0 {
54 let err = io::Error::last_os_error();
55 if err.kind() == io::ErrorKind::NotFound {
56 continue;
57 }
58
59 return None;
60 }
61
62 return Some(unsafe { OwnedFd::from_raw_fd(fd)});
63 }
64 }
65 }
66
67 impl Iterator for $name {
68 type Item = $info_ty;
69
70 fn next(&mut self) -> Option<Self::Item> {
71 let fd = self.next_valid_fd()?;
72
73 let mut item: $uapi_info_ty = unsafe { std::mem::zeroed() };
79 let item_ptr: *mut $uapi_info_ty = &mut item;
80 let mut len = size_of_val(&item) as u32;
81
82 let ret = unsafe { libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr as *mut c_void, &mut len) };
83 let parsed_uapi = if ret != 0 {
84 None
85 } else {
86 <$info_ty>::from_uapi(fd.as_fd(), item)
87 };
88
89 parsed_uapi
90 }
91 }
92 };
93}
94
95#[derive(Clone, Debug)]
97pub struct LineInfo {
98 pub insn_off: u32,
100 pub file_name_off: u32,
102 pub line_off: u32,
104 pub line_num: u32,
106 pub line_col: u32,
108}
109
110impl From<&libbpf_sys::bpf_line_info> for LineInfo {
111 fn from(item: &libbpf_sys::bpf_line_info) -> Self {
112 Self {
113 insn_off: item.insn_off,
114 file_name_off: item.file_name_off,
115 line_off: item.line_off,
116 line_num: item.line_col >> 10,
117 line_col: item.line_col & 0x3ff,
118 }
119 }
120}
121
122#[derive(Debug, Clone, Default)]
124#[repr(C)]
125pub struct Tag(pub [u8; 8]);
126
127#[derive(Debug, Clone)]
129pub struct ProgramInfo {
130 pub name: CString,
132 pub ty: ProgramType,
134 pub tag: Tag,
137 pub id: u32,
139 pub jited_prog_insns: Vec<u8>,
141 pub xlated_prog_insns: Vec<u8>,
143 pub load_time: Duration,
145 pub created_by_uid: u32,
147 pub map_ids: Vec<u32>,
149 pub ifindex: u32,
151 pub gpl_compatible: bool,
153 pub netns_dev: u64,
155 pub netns_ino: u64,
157 pub jited_ksyms: Vec<*const c_void>,
159 pub jited_func_lens: Vec<u32>,
161 pub btf_id: u32,
163 pub func_info_rec_size: u32,
165 pub func_info: Vec<libbpf_sys::bpf_func_info>,
167 pub line_info: Vec<LineInfo>,
169 pub jited_line_info: Vec<*const c_void>,
171 pub line_info_rec_size: u32,
173 pub jited_line_info_rec_size: u32,
175 pub prog_tags: Vec<Tag>,
177 pub run_time_ns: u64,
179 pub run_cnt: u64,
181 pub recursion_misses: u64,
183 pub verified_insns: u32,
185 #[doc(hidden)]
187 pub _non_exhaustive: (),
188}
189
190#[derive(Default, Debug)]
192pub struct ProgInfoIter {
193 cur_id: u32,
194 opts: ProgInfoQueryOptions,
195}
196
197#[derive(Clone, Default, Debug)]
199pub struct ProgInfoQueryOptions {
200 include_xlated_prog_insns: bool,
202 include_jited_prog_insns: bool,
204 include_map_ids: bool,
206 include_line_info: bool,
208 include_func_info: bool,
210 include_jited_line_info: bool,
212 include_jited_func_lens: bool,
214 include_prog_tags: bool,
216 include_jited_ksyms: bool,
218}
219
220impl ProgInfoIter {
221 pub fn with_query_opts(opts: ProgInfoQueryOptions) -> Self {
223 Self {
224 opts,
225 ..Self::default()
226 }
227 }
228}
229
230impl ProgInfoQueryOptions {
231 pub fn include_xlated_prog_insns(mut self, v: bool) -> Self {
233 self.include_xlated_prog_insns = v;
234 self
235 }
236
237 pub fn include_jited_prog_insns(mut self, v: bool) -> Self {
239 self.include_jited_prog_insns = v;
240 self
241 }
242
243 pub fn include_map_ids(mut self, v: bool) -> Self {
245 self.include_map_ids = v;
246 self
247 }
248
249 pub fn include_line_info(mut self, v: bool) -> Self {
251 self.include_line_info = v;
252 self
253 }
254
255 pub fn include_func_info(mut self, v: bool) -> Self {
257 self.include_func_info = v;
258 self
259 }
260
261 pub fn include_jited_line_info(mut self, v: bool) -> Self {
263 self.include_jited_line_info = v;
264 self
265 }
266
267 pub fn include_jited_func_lens(mut self, v: bool) -> Self {
269 self.include_jited_func_lens = v;
270 self
271 }
272
273 pub fn include_prog_tags(mut self, v: bool) -> Self {
275 self.include_prog_tags = v;
276 self
277 }
278
279 pub fn include_jited_ksyms(mut self, v: bool) -> Self {
281 self.include_jited_ksyms = v;
282 self
283 }
284
285 pub fn include_all(self) -> Self {
287 Self {
288 include_xlated_prog_insns: true,
289 include_jited_prog_insns: true,
290 include_map_ids: true,
291 include_line_info: true,
292 include_func_info: true,
293 include_jited_line_info: true,
294 include_jited_func_lens: true,
295 include_prog_tags: true,
296 include_jited_ksyms: true,
297 }
298 }
299}
300
301impl ProgramInfo {
302 fn load_from_fd(fd: BorrowedFd<'_>, opts: &ProgInfoQueryOptions) -> Result<Self> {
303 let mut item = libbpf_sys::bpf_prog_info::default();
304
305 let mut xlated_prog_insns: Vec<u8> = Vec::new();
306 let mut jited_prog_insns: Vec<u8> = Vec::new();
307 let mut map_ids: Vec<u32> = Vec::new();
308 let mut jited_line_info: Vec<*const c_void> = Vec::new();
309 let mut line_info: Vec<libbpf_sys::bpf_line_info> = Vec::new();
310 let mut func_info: Vec<libbpf_sys::bpf_func_info> = Vec::new();
311 let mut jited_func_lens: Vec<u32> = Vec::new();
312 let mut prog_tags: Vec<Tag> = Vec::new();
313 let mut jited_ksyms: Vec<*const c_void> = Vec::new();
314
315 let item_ptr: *mut libbpf_sys::bpf_prog_info = &mut item;
316 let mut len = size_of_val(&item) as u32;
317
318 let ret = unsafe {
319 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr as *mut c_void, &mut len)
320 };
321 util::parse_ret(ret)?;
322
323 let name = util::c_char_slice_to_cstr(&item.name).unwrap();
325 let ty = ProgramType::from(item.type_);
326
327 if opts.include_xlated_prog_insns {
328 xlated_prog_insns.resize(item.xlated_prog_len as usize, 0u8);
329 item.xlated_prog_insns = xlated_prog_insns.as_mut_ptr() as *mut c_void as u64;
330 } else {
331 item.xlated_prog_len = 0;
332 }
333
334 if opts.include_jited_prog_insns {
335 jited_prog_insns.resize(item.jited_prog_len as usize, 0u8);
336 item.jited_prog_insns = jited_prog_insns.as_mut_ptr() as *mut c_void as u64;
337 } else {
338 item.jited_prog_len = 0;
339 }
340
341 if opts.include_map_ids {
342 map_ids.resize(item.nr_map_ids as usize, 0u32);
343 item.map_ids = map_ids.as_mut_ptr() as *mut c_void as u64;
344 } else {
345 item.nr_map_ids = 0;
346 }
347
348 if opts.include_line_info {
349 line_info.resize(
350 item.nr_line_info as usize,
351 libbpf_sys::bpf_line_info::default(),
352 );
353 item.line_info = line_info.as_mut_ptr() as *mut c_void as u64;
354 } else {
355 item.nr_line_info = 0;
356 }
357
358 if opts.include_func_info {
359 func_info.resize(
360 item.nr_func_info as usize,
361 libbpf_sys::bpf_func_info::default(),
362 );
363 item.func_info = func_info.as_mut_ptr() as *mut c_void as u64;
364 } else {
365 item.nr_func_info = 0;
366 }
367
368 if opts.include_jited_line_info {
369 jited_line_info.resize(item.nr_jited_line_info as usize, ptr::null());
370 item.jited_line_info = jited_line_info.as_mut_ptr() as *mut c_void as u64;
371 } else {
372 item.nr_jited_line_info = 0;
373 }
374
375 if opts.include_jited_func_lens {
376 jited_func_lens.resize(item.nr_jited_func_lens as usize, 0);
377 item.jited_func_lens = jited_func_lens.as_mut_ptr() as *mut c_void as u64;
378 } else {
379 item.nr_jited_func_lens = 0;
380 }
381
382 if opts.include_prog_tags {
383 prog_tags.resize(item.nr_prog_tags as usize, Tag::default());
384 item.prog_tags = prog_tags.as_mut_ptr() as *mut c_void as u64;
385 } else {
386 item.nr_prog_tags = 0;
387 }
388
389 if opts.include_jited_ksyms {
390 jited_ksyms.resize(item.nr_jited_ksyms as usize, ptr::null());
391 item.jited_ksyms = jited_ksyms.as_mut_ptr() as *mut c_void as u64;
392 } else {
393 item.nr_jited_ksyms = 0;
394 }
395
396 let ret = unsafe {
397 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr as *mut c_void, &mut len)
398 };
399 util::parse_ret(ret)?;
400
401 Ok(Self {
402 name: name.to_owned(),
403 ty,
404 tag: Tag(item.tag),
405 id: item.id,
406 jited_prog_insns,
407 xlated_prog_insns,
408 load_time: Duration::from_nanos(item.load_time),
409 created_by_uid: item.created_by_uid,
410 map_ids,
411 ifindex: item.ifindex,
412 gpl_compatible: item._bitfield_1.get_bit(0),
413 netns_dev: item.netns_dev,
414 netns_ino: item.netns_ino,
415 jited_ksyms,
416 jited_func_lens,
417 btf_id: item.btf_id,
418 func_info_rec_size: item.func_info_rec_size,
419 func_info,
420 line_info: line_info.iter().map(Into::into).collect(),
421 jited_line_info,
422 line_info_rec_size: item.line_info_rec_size,
423 jited_line_info_rec_size: item.jited_line_info_rec_size,
424 prog_tags,
425 run_time_ns: item.run_time_ns,
426 run_cnt: item.run_cnt,
427 recursion_misses: item.recursion_misses,
428 verified_insns: item.verified_insns,
429 _non_exhaustive: (),
430 })
431 }
432}
433
434impl ProgInfoIter {
435 fn next_valid_fd(&mut self) -> Option<OwnedFd> {
436 loop {
437 if unsafe { libbpf_sys::bpf_prog_get_next_id(self.cur_id, &mut self.cur_id) } != 0 {
438 return None;
439 }
440
441 let fd = unsafe { libbpf_sys::bpf_prog_get_fd_by_id(self.cur_id) };
442 if fd < 0 {
443 let err = io::Error::last_os_error();
444 if err.kind() == io::ErrorKind::NotFound {
445 continue;
446 }
447 return None;
448 }
449
450 return Some(unsafe { OwnedFd::from_raw_fd(fd) });
451 }
452 }
453}
454
455impl Iterator for ProgInfoIter {
456 type Item = ProgramInfo;
457
458 fn next(&mut self) -> Option<Self::Item> {
459 let fd = self.next_valid_fd()?;
460 let prog = ProgramInfo::load_from_fd(fd.as_fd(), &self.opts);
461 prog.ok()
462 }
463}
464
465#[derive(Debug, Clone)]
467pub struct MapInfo {
468 pub name: CString,
470 pub ty: MapType,
472 pub id: u32,
474 pub key_size: u32,
476 pub value_size: u32,
478 pub max_entries: u32,
480 pub map_flags: u32,
482 pub ifindex: u32,
485 pub btf_vmlinux_value_type_id: u32,
487 pub netns_dev: u64,
489 pub netns_ino: u64,
491 pub btf_id: u32,
494 pub btf_key_type_id: u32,
496 pub btf_value_type_id: u32,
498}
499
500impl MapInfo {
501 fn from_uapi(_fd: BorrowedFd<'_>, s: libbpf_sys::bpf_map_info) -> Option<Self> {
502 let name = util::c_char_slice_to_cstr(&s.name).unwrap();
504 let ty = MapType::from(s.type_);
505
506 Some(Self {
507 name: name.to_owned(),
508 ty,
509 id: s.id,
510 key_size: s.key_size,
511 value_size: s.value_size,
512 max_entries: s.max_entries,
513 map_flags: s.map_flags,
514 ifindex: s.ifindex,
515 btf_vmlinux_value_type_id: s.btf_vmlinux_value_type_id,
516 netns_dev: s.netns_dev,
517 netns_ino: s.netns_ino,
518 btf_id: s.btf_id,
519 btf_key_type_id: s.btf_key_type_id,
520 btf_value_type_id: s.btf_value_type_id,
521 })
522 }
523}
524
525gen_info_impl!(
526 MapInfoIter,
528 MapInfo,
529 libbpf_sys::bpf_map_info,
530 libbpf_sys::bpf_map_get_next_id,
531 libbpf_sys::bpf_map_get_fd_by_id
532);
533
534#[derive(Debug, Clone)]
536pub struct BtfInfo {
537 pub name: CString,
539 pub btf: Vec<u8>,
541 pub id: u32,
543}
544
545impl BtfInfo {
546 fn load_from_fd(fd: BorrowedFd<'_>) -> Result<Self> {
547 let mut item = libbpf_sys::bpf_btf_info::default();
548 let mut btf: Vec<u8> = Vec::new();
549 let mut name: Vec<u8> = Vec::new();
550
551 let item_ptr: *mut libbpf_sys::bpf_btf_info = &mut item;
552 let mut len = size_of_val(&item) as u32;
553
554 let ret = unsafe {
555 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr as *mut c_void, &mut len)
556 };
557 util::parse_ret(ret)?;
558
559 item.name_len += 1;
562 name.resize(item.name_len as usize, 0u8);
563 item.name = name.as_mut_ptr() as *mut c_void as u64;
564
565 btf.resize(item.btf_size as usize, 0u8);
566 item.btf = btf.as_mut_ptr() as *mut c_void as u64;
567
568 let ret = unsafe {
569 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr as *mut c_void, &mut len)
570 };
571 util::parse_ret(ret)?;
572
573 Ok(Self {
574 name: CString::from_vec_with_nul(name).unwrap(),
578 btf,
579 id: item.id,
580 })
581 }
582}
583
584#[derive(Debug, Default)]
585pub struct BtfInfoIter {
588 cur_id: u32,
589}
590
591impl BtfInfoIter {
592 fn next_valid_fd(&mut self) -> Option<OwnedFd> {
594 loop {
595 if unsafe { libbpf_sys::bpf_btf_get_next_id(self.cur_id, &mut self.cur_id) } != 0 {
596 return None;
597 }
598
599 let fd = unsafe { libbpf_sys::bpf_btf_get_fd_by_id(self.cur_id) };
600 if fd < 0 {
601 let err = io::Error::last_os_error();
602 if err.kind() == io::ErrorKind::NotFound {
603 continue;
604 }
605 return None;
606 }
607
608 return Some(unsafe { OwnedFd::from_raw_fd(fd) });
609 }
610 }
611}
612
613impl Iterator for BtfInfoIter {
614 type Item = BtfInfo;
615
616 fn next(&mut self) -> Option<Self::Item> {
617 let fd = self.next_valid_fd()?;
618 let info = BtfInfo::load_from_fd(fd.as_fd());
619 info.ok()
620 }
621}
622
623#[derive(Debug, Clone)]
625pub struct RawTracepointLinkInfo {
626 pub name: String,
628}
629
630#[derive(Debug, Clone)]
632pub struct TracingLinkInfo {
633 pub attach_type: ProgramAttachType,
635 pub target_obj_id: u32,
638 pub target_btf_id: u32,
640}
641
642#[derive(Debug, Clone)]
644pub struct CgroupLinkInfo {
645 pub cgroup_id: u64,
647 pub attach_type: ProgramAttachType,
649}
650
651#[derive(Debug, Clone)]
653pub struct NetNsLinkInfo {
654 pub ino: u32,
656 pub attach_type: ProgramAttachType,
658}
659
660#[derive(Debug, Clone)]
662pub struct NetfilterLinkInfo {
663 pub protocol_family: u32,
665 pub hooknum: u32,
667 pub priority: i32,
669 pub flags: u32,
671}
672
673#[derive(Debug, Clone)]
675pub struct XdpLinkInfo {
676 pub ifindex: u32,
678}
679
680#[derive(Debug, Clone)]
682pub struct SockMapLinkInfo {
683 pub map_id: u32,
685 pub attach_type: ProgramAttachType,
687}
688
689#[derive(Debug, Clone)]
691pub struct NetkitLinkInfo {
692 pub ifindex: u32,
694 pub attach_type: ProgramAttachType,
696}
697
698#[derive(Debug, Clone)]
700pub struct TcxLinkInfo {
701 pub ifindex: u32,
703 pub attach_type: ProgramAttachType,
705}
706
707#[derive(Debug, Clone)]
709pub struct StructOpsLinkInfo {
710 pub map_id: u32,
712}
713
714#[derive(Debug, Clone)]
716pub struct KprobeMultiLinkInfo {
717 pub count: u32,
719 pub flags: u32,
721 pub missed: u64,
723}
724
725#[derive(Debug, Clone)]
727pub struct UprobeMultiLinkInfo {
728 pub path_size: u32,
730 pub count: u32,
732 pub flags: u32,
734 pub pid: u32,
736}
737
738#[derive(Debug, Clone)]
740pub struct PerfEventLinkInfo {
741 pub event_type: PerfEventType,
743}
744
745#[derive(Debug, Clone)]
747pub enum PerfEventType {
748 Tracepoint {
750 name: Option<CString>,
752 cookie: u64,
754 },
755 Kprobe {
757 func_name: Option<CString>,
759 is_retprobe: bool,
761 addr: u64,
763 offset: u32,
765 missed: u64,
767 cookie: u64,
769 },
770 Uprobe {
772 file_name: Option<CString>,
774 is_retprobe: bool,
776 offset: u32,
778 cookie: u64,
780 ref_ctr_offset: u64,
782 },
783 Event {
785 config: u64,
787 event_type: u32,
789 cookie: u64,
791 },
792 Unknown(u32),
794}
795
796#[derive(Debug, Clone)]
799pub enum LinkTypeInfo {
800 RawTracepoint(RawTracepointLinkInfo),
804 Tracing(TracingLinkInfo),
806 Cgroup(CgroupLinkInfo),
810 Iter,
812 NetNs(NetNsLinkInfo),
814 Xdp(XdpLinkInfo),
819 StructOps(StructOpsLinkInfo),
824 Netfilter(NetfilterLinkInfo),
826 KprobeMulti(KprobeMultiLinkInfo),
828 UprobeMulti(UprobeMultiLinkInfo),
830 Tcx(TcxLinkInfo),
832 Netkit(NetkitLinkInfo),
834 SockMap(SockMapLinkInfo),
836 PerfEvent(PerfEventLinkInfo),
841 Unknown,
843}
844
845#[derive(Debug, Clone)]
847pub struct LinkInfo {
848 pub info: LinkTypeInfo,
850 pub id: u32,
852 pub prog_id: u32,
854}
855
856impl LinkInfo {
857 pub fn from_fd(fd: BorrowedFd<'_>) -> Result<Self> {
859 let mut link_info: libbpf_sys::bpf_link_info = unsafe { zeroed() };
861 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut link_info;
862 let mut len = size_of_val(&link_info) as u32;
863
864 let ret = unsafe {
865 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr as *mut c_void, &mut len)
866 };
867 util::parse_ret(ret)?;
868
869 Self::from_uapi(fd, link_info)
870 .ok_or_else(|| crate::Error::with_invalid_data("failed to parse link info"))
871 }
872
873 fn from_uapi(fd: BorrowedFd<'_>, mut s: libbpf_sys::bpf_link_info) -> Option<Self> {
874 let type_info = match s.type_ {
875 libbpf_sys::BPF_LINK_TYPE_RAW_TRACEPOINT => {
876 let mut buf = [0; 256];
877 s.__bindgen_anon_1.raw_tracepoint.tp_name = buf.as_mut_ptr() as u64;
878 s.__bindgen_anon_1.raw_tracepoint.tp_name_len = buf.len() as u32;
879 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
880 let mut len = size_of_val(&s) as u32;
881
882 let ret = unsafe {
883 libbpf_sys::bpf_obj_get_info_by_fd(
884 fd.as_raw_fd(),
885 item_ptr as *mut c_void,
886 &mut len,
887 )
888 };
889 if ret != 0 {
890 return None;
891 }
892
893 LinkTypeInfo::RawTracepoint(RawTracepointLinkInfo {
894 name: util::c_ptr_to_string(
895 unsafe { s.__bindgen_anon_1.raw_tracepoint.tp_name } as *const c_char,
896 )
897 .unwrap_or_else(|_| "?".to_string()),
898 })
899 }
900 libbpf_sys::BPF_LINK_TYPE_TRACING => LinkTypeInfo::Tracing(TracingLinkInfo {
901 attach_type: ProgramAttachType::from(unsafe {
902 s.__bindgen_anon_1.tracing.attach_type
903 }),
904 target_obj_id: unsafe { s.__bindgen_anon_1.tracing.target_obj_id },
905 target_btf_id: unsafe { s.__bindgen_anon_1.tracing.target_btf_id },
906 }),
907 libbpf_sys::BPF_LINK_TYPE_CGROUP => LinkTypeInfo::Cgroup(CgroupLinkInfo {
908 cgroup_id: unsafe { s.__bindgen_anon_1.cgroup.cgroup_id },
909 attach_type: ProgramAttachType::from(unsafe {
910 s.__bindgen_anon_1.cgroup.attach_type
911 }),
912 }),
913 libbpf_sys::BPF_LINK_TYPE_ITER => LinkTypeInfo::Iter,
914 libbpf_sys::BPF_LINK_TYPE_NETNS => LinkTypeInfo::NetNs(NetNsLinkInfo {
915 ino: unsafe { s.__bindgen_anon_1.netns.netns_ino },
916 attach_type: ProgramAttachType::from(unsafe {
917 s.__bindgen_anon_1.netns.attach_type
918 }),
919 }),
920 libbpf_sys::BPF_LINK_TYPE_NETFILTER => LinkTypeInfo::Netfilter(NetfilterLinkInfo {
921 protocol_family: unsafe { s.__bindgen_anon_1.netfilter.pf },
922 hooknum: unsafe { s.__bindgen_anon_1.netfilter.hooknum },
923 priority: unsafe { s.__bindgen_anon_1.netfilter.priority },
924 flags: unsafe { s.__bindgen_anon_1.netfilter.flags },
925 }),
926 libbpf_sys::BPF_LINK_TYPE_XDP => LinkTypeInfo::Xdp(XdpLinkInfo {
927 ifindex: unsafe { s.__bindgen_anon_1.xdp.ifindex },
928 }),
929 libbpf_sys::BPF_LINK_TYPE_NETKIT => LinkTypeInfo::Netkit(NetkitLinkInfo {
930 ifindex: unsafe { s.__bindgen_anon_1.netkit.ifindex },
931 attach_type: ProgramAttachType::from(unsafe {
932 s.__bindgen_anon_1.netkit.attach_type
933 }),
934 }),
935 libbpf_sys::BPF_LINK_TYPE_TCX => LinkTypeInfo::Tcx(TcxLinkInfo {
936 ifindex: unsafe { s.__bindgen_anon_1.tcx.ifindex },
937 attach_type: ProgramAttachType::from(unsafe { s.__bindgen_anon_1.tcx.attach_type }),
938 }),
939 libbpf_sys::BPF_LINK_TYPE_STRUCT_OPS => LinkTypeInfo::StructOps(StructOpsLinkInfo {
940 map_id: unsafe { s.__bindgen_anon_1.struct_ops.map_id },
941 }),
942 libbpf_sys::BPF_LINK_TYPE_KPROBE_MULTI => {
943 LinkTypeInfo::KprobeMulti(KprobeMultiLinkInfo {
944 count: unsafe { s.__bindgen_anon_1.kprobe_multi.count },
945 flags: unsafe { s.__bindgen_anon_1.kprobe_multi.flags },
946 missed: unsafe { s.__bindgen_anon_1.kprobe_multi.missed },
947 })
948 }
949 libbpf_sys::BPF_LINK_TYPE_UPROBE_MULTI => {
950 LinkTypeInfo::UprobeMulti(UprobeMultiLinkInfo {
951 path_size: unsafe { s.__bindgen_anon_1.uprobe_multi.path_size },
952 count: unsafe { s.__bindgen_anon_1.uprobe_multi.count },
953 flags: unsafe { s.__bindgen_anon_1.uprobe_multi.flags },
954 pid: unsafe { s.__bindgen_anon_1.uprobe_multi.pid },
955 })
956 }
957 libbpf_sys::BPF_LINK_TYPE_SOCKMAP => LinkTypeInfo::SockMap(SockMapLinkInfo {
958 map_id: unsafe { s.__bindgen_anon_1.sockmap.map_id },
959 attach_type: ProgramAttachType::from(unsafe {
960 s.__bindgen_anon_1.sockmap.attach_type
961 }),
962 }),
963 libbpf_sys::BPF_LINK_TYPE_PERF_EVENT => {
964 let bpf_perf_event_type = unsafe { s.__bindgen_anon_1.perf_event.type_ };
966
967 let mut buf = [0u8; libc::PATH_MAX as usize];
973 let call_get_info_again = match bpf_perf_event_type {
974 libbpf_sys::BPF_PERF_EVENT_TRACEPOINT => {
975 s.__bindgen_anon_1
976 .perf_event
977 .__bindgen_anon_1
978 .tracepoint
979 .tp_name = buf.as_mut_ptr() as u64;
980 s.__bindgen_anon_1
981 .perf_event
982 .__bindgen_anon_1
983 .tracepoint
984 .name_len = buf.len() as u32;
985 true
986 }
987 libbpf_sys::BPF_PERF_EVENT_KPROBE | libbpf_sys::BPF_PERF_EVENT_KRETPROBE => {
988 s.__bindgen_anon_1
989 .perf_event
990 .__bindgen_anon_1
991 .kprobe
992 .func_name = buf.as_mut_ptr() as u64;
993 s.__bindgen_anon_1
994 .perf_event
995 .__bindgen_anon_1
996 .kprobe
997 .name_len = buf.len() as u32;
998 true
999 }
1000 libbpf_sys::BPF_PERF_EVENT_UPROBE | libbpf_sys::BPF_PERF_EVENT_URETPROBE => {
1001 let uprobe =
1003 unsafe { &mut s.__bindgen_anon_1.perf_event.__bindgen_anon_1.uprobe };
1004 uprobe.file_name = buf.as_mut_ptr() as u64;
1005 uprobe.name_len = buf.len() as u32;
1006 true
1007 }
1008 _ => false,
1009 };
1010
1011 if call_get_info_again {
1012 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
1013 let mut len = size_of_val(&s) as u32;
1014 let ret = unsafe {
1015 libbpf_sys::bpf_obj_get_info_by_fd(
1016 fd.as_raw_fd(),
1017 item_ptr as *mut c_void,
1018 &mut len,
1019 )
1020 };
1021 if ret != 0 {
1022 return None;
1023 }
1024 }
1025
1026 let event_type = match bpf_perf_event_type {
1027 libbpf_sys::BPF_PERF_EVENT_TRACEPOINT => {
1028 let tp_name = unsafe {
1029 s.__bindgen_anon_1
1030 .perf_event
1031 .__bindgen_anon_1
1032 .tracepoint
1033 .tp_name
1034 };
1035 let cookie = unsafe {
1036 s.__bindgen_anon_1
1037 .perf_event
1038 .__bindgen_anon_1
1039 .tracepoint
1040 .cookie
1041 };
1042 let name = (tp_name != 0).then(|| unsafe {
1043 CStr::from_ptr(tp_name as *const c_char).to_owned()
1044 });
1045
1046 PerfEventType::Tracepoint { name, cookie }
1047 }
1048 libbpf_sys::BPF_PERF_EVENT_KPROBE | libbpf_sys::BPF_PERF_EVENT_KRETPROBE => {
1049 let func_name = unsafe {
1050 s.__bindgen_anon_1
1051 .perf_event
1052 .__bindgen_anon_1
1053 .kprobe
1054 .func_name
1055 };
1056 let addr =
1057 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.addr };
1058 let offset =
1059 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.offset };
1060 let missed =
1061 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.missed };
1062 let cookie =
1063 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.cookie };
1064 let func_name = (func_name != 0).then(|| unsafe {
1065 CStr::from_ptr(func_name as *const c_char).to_owned()
1066 });
1067
1068 let is_retprobe =
1069 bpf_perf_event_type == libbpf_sys::BPF_PERF_EVENT_KRETPROBE;
1070 PerfEventType::Kprobe {
1071 func_name,
1072 is_retprobe,
1073 addr,
1074 offset,
1075 missed,
1076 cookie,
1077 }
1078 }
1079 libbpf_sys::BPF_PERF_EVENT_UPROBE | libbpf_sys::BPF_PERF_EVENT_URETPROBE => {
1080 let uprobe =
1082 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.uprobe };
1083 let file_name = (uprobe.file_name != 0).then(|| unsafe {
1085 CStr::from_ptr(uprobe.file_name as *const c_char).to_owned()
1086 });
1087
1088 PerfEventType::Uprobe {
1089 file_name,
1090 is_retprobe: bpf_perf_event_type
1091 == libbpf_sys::BPF_PERF_EVENT_URETPROBE,
1092 offset: uprobe.offset,
1093 cookie: uprobe.cookie,
1094 ref_ctr_offset: uprobe.ref_ctr_offset,
1095 }
1096 }
1097 libbpf_sys::BPF_PERF_EVENT_EVENT => {
1098 let event = unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.event };
1100
1101 PerfEventType::Event {
1102 config: event.config,
1103 event_type: event.type_,
1104 cookie: event.cookie,
1105 }
1106 }
1107 ty => PerfEventType::Unknown(ty),
1108 };
1109
1110 LinkTypeInfo::PerfEvent(PerfEventLinkInfo { event_type })
1111 }
1112 _ => LinkTypeInfo::Unknown,
1113 };
1114
1115 Some(Self {
1116 info: type_info,
1117 id: s.id,
1118 prog_id: s.prog_id,
1119 })
1120 }
1121}
1122
1123gen_info_impl!(
1124 LinkInfoIter,
1126 LinkInfo,
1127 libbpf_sys::bpf_link_info,
1128 libbpf_sys::bpf_link_get_next_id,
1129 libbpf_sys::bpf_link_get_fd_by_id
1130);