|
11 | 11 | //! ```
|
12 | 12 |
|
13 | 13 | use std::ffi::c_void;
|
| 14 | +use std::ffi::CStr; |
14 | 15 | use std::ffi::CString;
|
15 | 16 | use std::io;
|
16 | 17 | use std::mem::size_of_val;
|
@@ -726,6 +727,43 @@ pub struct UprobeMultiLinkInfo {
|
726 | 727 | pub pid: u32,
|
727 | 728 | }
|
728 | 729 |
|
| 730 | +/// Information about a perf event link. |
| 731 | +#[derive(Debug, Clone)] |
| 732 | +pub struct PerfEventLinkInfo { |
| 733 | + /// The specific type of perf event with decoded information. |
| 734 | + pub event_type: PerfEventType, |
| 735 | +} |
| 736 | + |
| 737 | +/// Specific types of perf events with decoded information. |
| 738 | +#[derive(Debug, Clone)] |
| 739 | +pub enum PerfEventType { |
| 740 | + /// A tracepoint event. |
| 741 | + Tracepoint { |
| 742 | + /// The tracepoint name. |
| 743 | + name: Option<CString>, |
| 744 | + /// Attach cookie value for this link. |
| 745 | + cookie: u64, |
| 746 | + }, |
| 747 | + /// A kprobe event (includes both kprobe and kretprobe). |
| 748 | + Kprobe { |
| 749 | + /// The function being probed. |
| 750 | + func_name: Option<CString>, |
| 751 | + /// Whether this is a return probe (kretprobe). |
| 752 | + is_retprobe: bool, |
| 753 | + /// Address of the probe. |
| 754 | + addr: u64, |
| 755 | + /// Offset from the function. |
| 756 | + offset: u32, |
| 757 | + /// Number of missed events. |
| 758 | + missed: u64, |
| 759 | + /// Cookie value for the kprobe. |
| 760 | + cookie: u64, |
| 761 | + }, |
| 762 | + /// TODO: Add support for `BPF_PERF_EVENT_EVENT`, `BPF_PERF_EVENT_UPROBE` |
| 763 | + /// `BPF_PERF_EVENT_URETPROBE` |
| 764 | + Unknown(u32), |
| 765 | +} |
| 766 | + |
729 | 767 | /// Information about BPF link types. Maps to the anonymous union in `struct bpf_link_info` in
|
730 | 768 | /// kernel uapi.
|
731 | 769 | #[derive(Debug, Clone)]
|
@@ -767,7 +805,10 @@ pub enum LinkTypeInfo {
|
767 | 805 | /// Link type for sockmap programs.
|
768 | 806 | SockMap(SockMapLinkInfo),
|
769 | 807 | /// Link type for perf-event programs.
|
770 |
| - PerfEvent, |
| 808 | + /// |
| 809 | + /// Contains information about the perf event configuration including type and config |
| 810 | + /// which can be used to identify tracepoints, kprobes, uprobes, etc. |
| 811 | + PerfEvent(PerfEventLinkInfo), |
771 | 812 | /// Unknown link type.
|
772 | 813 | Unknown,
|
773 | 814 | }
|
@@ -874,7 +915,116 @@ impl LinkInfo {
|
874 | 915 | s.__bindgen_anon_1.sockmap.attach_type
|
875 | 916 | }),
|
876 | 917 | }),
|
877 |
| - libbpf_sys::BPF_LINK_TYPE_PERF_EVENT => LinkTypeInfo::PerfEvent, |
| 918 | + libbpf_sys::BPF_LINK_TYPE_PERF_EVENT => { |
| 919 | + // Get the BPF perf event type (BPF_PERF_EVENT_*) from the link info. |
| 920 | + let bpf_perf_event_type = unsafe { s.__bindgen_anon_1.perf_event.type_ }; |
| 921 | + |
| 922 | + // Handle two-phase call for perf event string data if needed (this mimics the |
| 923 | + // behavior of bpftool). |
| 924 | + let mut buf = [0u8; 256]; |
| 925 | + let need_second_call = match bpf_perf_event_type { |
| 926 | + libbpf_sys::BPF_PERF_EVENT_TRACEPOINT => { |
| 927 | + s.__bindgen_anon_1 |
| 928 | + .perf_event |
| 929 | + .__bindgen_anon_1 |
| 930 | + .tracepoint |
| 931 | + .tp_name = buf.as_mut_ptr() as u64; |
| 932 | + s.__bindgen_anon_1 |
| 933 | + .perf_event |
| 934 | + .__bindgen_anon_1 |
| 935 | + .tracepoint |
| 936 | + .name_len = buf.len() as u32; |
| 937 | + true |
| 938 | + } |
| 939 | + libbpf_sys::BPF_PERF_EVENT_KPROBE | libbpf_sys::BPF_PERF_EVENT_KRETPROBE => { |
| 940 | + s.__bindgen_anon_1 |
| 941 | + .perf_event |
| 942 | + .__bindgen_anon_1 |
| 943 | + .kprobe |
| 944 | + .func_name = buf.as_mut_ptr() as u64; |
| 945 | + s.__bindgen_anon_1 |
| 946 | + .perf_event |
| 947 | + .__bindgen_anon_1 |
| 948 | + .kprobe |
| 949 | + .name_len = buf.len() as u32; |
| 950 | + true |
| 951 | + } |
| 952 | + _ => false, |
| 953 | + }; |
| 954 | + |
| 955 | + if need_second_call { |
| 956 | + let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s; |
| 957 | + let mut len = size_of_val(&s) as u32; |
| 958 | + let ret = unsafe { |
| 959 | + libbpf_sys::bpf_obj_get_info_by_fd( |
| 960 | + fd.as_raw_fd(), |
| 961 | + item_ptr as *mut c_void, |
| 962 | + &mut len, |
| 963 | + ) |
| 964 | + }; |
| 965 | + if ret != 0 { |
| 966 | + return None; |
| 967 | + } |
| 968 | + } |
| 969 | + |
| 970 | + let event_type = match bpf_perf_event_type { |
| 971 | + libbpf_sys::BPF_PERF_EVENT_TRACEPOINT => { |
| 972 | + let tp_name = unsafe { |
| 973 | + s.__bindgen_anon_1 |
| 974 | + .perf_event |
| 975 | + .__bindgen_anon_1 |
| 976 | + .tracepoint |
| 977 | + .tp_name |
| 978 | + }; |
| 979 | + let cookie = unsafe { |
| 980 | + s.__bindgen_anon_1 |
| 981 | + .perf_event |
| 982 | + .__bindgen_anon_1 |
| 983 | + .tracepoint |
| 984 | + .cookie |
| 985 | + }; |
| 986 | + let name = (tp_name != 0).then(|| unsafe { |
| 987 | + CStr::from_ptr(tp_name as *const c_char).to_owned() |
| 988 | + }); |
| 989 | + |
| 990 | + PerfEventType::Tracepoint { name, cookie } |
| 991 | + } |
| 992 | + libbpf_sys::BPF_PERF_EVENT_KPROBE | libbpf_sys::BPF_PERF_EVENT_KRETPROBE => { |
| 993 | + let func_name = unsafe { |
| 994 | + s.__bindgen_anon_1 |
| 995 | + .perf_event |
| 996 | + .__bindgen_anon_1 |
| 997 | + .kprobe |
| 998 | + .func_name |
| 999 | + }; |
| 1000 | + let addr = |
| 1001 | + unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.addr }; |
| 1002 | + let offset = |
| 1003 | + unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.offset }; |
| 1004 | + let missed = |
| 1005 | + unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.missed }; |
| 1006 | + let cookie = |
| 1007 | + unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.cookie }; |
| 1008 | + let func_name = (func_name != 0).then(|| unsafe { |
| 1009 | + CStr::from_ptr(func_name as *const c_char).to_owned() |
| 1010 | + }); |
| 1011 | + |
| 1012 | + let is_retprobe = |
| 1013 | + bpf_perf_event_type == libbpf_sys::BPF_PERF_EVENT_KRETPROBE; |
| 1014 | + PerfEventType::Kprobe { |
| 1015 | + func_name, |
| 1016 | + is_retprobe, |
| 1017 | + addr, |
| 1018 | + offset, |
| 1019 | + missed, |
| 1020 | + cookie, |
| 1021 | + } |
| 1022 | + } |
| 1023 | + ty => PerfEventType::Unknown(ty), |
| 1024 | + }; |
| 1025 | + |
| 1026 | + LinkTypeInfo::PerfEvent(PerfEventLinkInfo { event_type }) |
| 1027 | + } |
878 | 1028 | _ => LinkTypeInfo::Unknown,
|
879 | 1029 | };
|
880 | 1030 |
|
|
0 commit comments