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