@@ -841,7 +841,8 @@ static void test_tp_attach_query(void)
841
841
static int compare_map_keys (int map1_fd , int map2_fd )
842
842
{
843
843
__u32 key , next_key ;
844
- char val_buf [PERF_MAX_STACK_DEPTH * sizeof (__u64 )];
844
+ char val_buf [PERF_MAX_STACK_DEPTH *
845
+ sizeof (struct bpf_stack_build_id )];
845
846
int err ;
846
847
847
848
err = bpf_map_get_next_key (map1_fd , NULL , & key );
@@ -964,6 +965,166 @@ static void test_stacktrace_map()
964
965
return ;
965
966
}
966
967
968
+ static int extract_build_id (char * build_id , size_t size )
969
+ {
970
+ FILE * fp ;
971
+ char * line = NULL ;
972
+ size_t len = 0 ;
973
+
974
+ fp = popen ("readelf -n ./urandom_read | grep 'Build ID'" , "r" );
975
+ if (fp == NULL )
976
+ return -1 ;
977
+
978
+ if (getline (& line , & len , fp ) == -1 )
979
+ goto err ;
980
+ fclose (fp );
981
+
982
+ if (len > size )
983
+ len = size ;
984
+ memcpy (build_id , line , len );
985
+ build_id [len ] = '\0' ;
986
+ return 0 ;
987
+ err :
988
+ fclose (fp );
989
+ return -1 ;
990
+ }
991
+
992
+ static void test_stacktrace_build_id (void )
993
+ {
994
+ int control_map_fd , stackid_hmap_fd , stackmap_fd ;
995
+ const char * file = "./test_stacktrace_build_id.o" ;
996
+ int bytes , efd , err , pmu_fd , prog_fd ;
997
+ struct perf_event_attr attr = {};
998
+ __u32 key , previous_key , val , duration = 0 ;
999
+ struct bpf_object * obj ;
1000
+ char buf [256 ];
1001
+ int i , j ;
1002
+ struct bpf_stack_build_id id_offs [PERF_MAX_STACK_DEPTH ];
1003
+ int build_id_matches = 0 ;
1004
+
1005
+ err = bpf_prog_load (file , BPF_PROG_TYPE_TRACEPOINT , & obj , & prog_fd );
1006
+ if (CHECK (err , "prog_load" , "err %d errno %d\n" , err , errno ))
1007
+ goto out ;
1008
+
1009
+ /* Get the ID for the sched/sched_switch tracepoint */
1010
+ snprintf (buf , sizeof (buf ),
1011
+ "/sys/kernel/debug/tracing/events/random/urandom_read/id" );
1012
+ efd = open (buf , O_RDONLY , 0 );
1013
+ if (CHECK (efd < 0 , "open" , "err %d errno %d\n" , efd , errno ))
1014
+ goto close_prog ;
1015
+
1016
+ bytes = read (efd , buf , sizeof (buf ));
1017
+ close (efd );
1018
+ if (CHECK (bytes <= 0 || bytes >= sizeof (buf ),
1019
+ "read" , "bytes %d errno %d\n" , bytes , errno ))
1020
+ goto close_prog ;
1021
+
1022
+ /* Open the perf event and attach bpf progrram */
1023
+ attr .config = strtol (buf , NULL , 0 );
1024
+ attr .type = PERF_TYPE_TRACEPOINT ;
1025
+ attr .sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN ;
1026
+ attr .sample_period = 1 ;
1027
+ attr .wakeup_events = 1 ;
1028
+ pmu_fd = syscall (__NR_perf_event_open , & attr , -1 /* pid */ ,
1029
+ 0 /* cpu 0 */ , -1 /* group id */ ,
1030
+ 0 /* flags */ );
1031
+ if (CHECK (pmu_fd < 0 , "perf_event_open" , "err %d errno %d\n" ,
1032
+ pmu_fd , errno ))
1033
+ goto close_prog ;
1034
+
1035
+ err = ioctl (pmu_fd , PERF_EVENT_IOC_ENABLE , 0 );
1036
+ if (CHECK (err , "perf_event_ioc_enable" , "err %d errno %d\n" ,
1037
+ err , errno ))
1038
+ goto close_pmu ;
1039
+
1040
+ err = ioctl (pmu_fd , PERF_EVENT_IOC_SET_BPF , prog_fd );
1041
+ if (CHECK (err , "perf_event_ioc_set_bpf" , "err %d errno %d\n" ,
1042
+ err , errno ))
1043
+ goto disable_pmu ;
1044
+
1045
+ /* find map fds */
1046
+ control_map_fd = bpf_find_map (__func__ , obj , "control_map" );
1047
+ if (CHECK (control_map_fd < 0 , "bpf_find_map control_map" ,
1048
+ "err %d errno %d\n" , err , errno ))
1049
+ goto disable_pmu ;
1050
+
1051
+ stackid_hmap_fd = bpf_find_map (__func__ , obj , "stackid_hmap" );
1052
+ if (CHECK (stackid_hmap_fd < 0 , "bpf_find_map stackid_hmap" ,
1053
+ "err %d errno %d\n" , err , errno ))
1054
+ goto disable_pmu ;
1055
+
1056
+ stackmap_fd = bpf_find_map (__func__ , obj , "stackmap" );
1057
+ if (CHECK (stackmap_fd < 0 , "bpf_find_map stackmap" , "err %d errno %d\n" ,
1058
+ err , errno ))
1059
+ goto disable_pmu ;
1060
+
1061
+ assert (system ("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null" )
1062
+ == 0 );
1063
+ assert (system ("./urandom_read if=/dev/urandom of=/dev/zero count=4 2> /dev/null" ) == 0 );
1064
+ /* disable stack trace collection */
1065
+ key = 0 ;
1066
+ val = 1 ;
1067
+ bpf_map_update_elem (control_map_fd , & key , & val , 0 );
1068
+
1069
+ /* for every element in stackid_hmap, we can find a corresponding one
1070
+ * in stackmap, and vise versa.
1071
+ */
1072
+ err = compare_map_keys (stackid_hmap_fd , stackmap_fd );
1073
+ if (CHECK (err , "compare_map_keys stackid_hmap vs. stackmap" ,
1074
+ "err %d errno %d\n" , err , errno ))
1075
+ goto disable_pmu ;
1076
+
1077
+ err = compare_map_keys (stackmap_fd , stackid_hmap_fd );
1078
+ if (CHECK (err , "compare_map_keys stackmap vs. stackid_hmap" ,
1079
+ "err %d errno %d\n" , err , errno ))
1080
+ goto disable_pmu ;
1081
+
1082
+ err = extract_build_id (buf , 256 );
1083
+
1084
+ if (CHECK (err , "get build_id with readelf" ,
1085
+ "err %d errno %d\n" , err , errno ))
1086
+ goto disable_pmu ;
1087
+
1088
+ err = bpf_map_get_next_key (stackmap_fd , NULL , & key );
1089
+ if (CHECK (err , "get_next_key from stackmap" ,
1090
+ "err %d, errno %d\n" , err , errno ))
1091
+ goto disable_pmu ;
1092
+
1093
+ do {
1094
+ char build_id [64 ];
1095
+
1096
+ err = bpf_map_lookup_elem (stackmap_fd , & key , id_offs );
1097
+ if (CHECK (err , "lookup_elem from stackmap" ,
1098
+ "err %d, errno %d\n" , err , errno ))
1099
+ goto disable_pmu ;
1100
+ for (i = 0 ; i < PERF_MAX_STACK_DEPTH ; ++ i )
1101
+ if (id_offs [i ].status == BPF_STACK_BUILD_ID_VALID &&
1102
+ id_offs [i ].offset != 0 ) {
1103
+ for (j = 0 ; j < 20 ; ++ j )
1104
+ sprintf (build_id + 2 * j , "%02x" ,
1105
+ id_offs [i ].build_id [j ] & 0xff );
1106
+ if (strstr (buf , build_id ) != NULL )
1107
+ build_id_matches = 1 ;
1108
+ }
1109
+ previous_key = key ;
1110
+ } while (bpf_map_get_next_key (stackmap_fd , & previous_key , & key ) == 0 );
1111
+
1112
+ CHECK (build_id_matches < 1 , "build id match" ,
1113
+ "Didn't find expected build ID from the map" );
1114
+
1115
+ disable_pmu :
1116
+ ioctl (pmu_fd , PERF_EVENT_IOC_DISABLE );
1117
+
1118
+ close_pmu :
1119
+ close (pmu_fd );
1120
+
1121
+ close_prog :
1122
+ bpf_object__close (obj );
1123
+
1124
+ out :
1125
+ return ;
1126
+ }
1127
+
967
1128
int main (void )
968
1129
{
969
1130
test_pkt_access ();
@@ -976,6 +1137,7 @@ int main(void)
976
1137
test_obj_name ();
977
1138
test_tp_attach_query ();
978
1139
test_stacktrace_map ();
1140
+ test_stacktrace_build_id ();
979
1141
980
1142
printf ("Summary: %d PASSED, %d FAILED\n" , pass_cnt , error_cnt );
981
1143
return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS ;
0 commit comments