@@ -126,3 +126,114 @@ void test_libbpf_probe_helpers(void)
126126 ASSERT_EQ (res , d -> supported , buf );
127127 }
128128}
129+
130+ static int module_btf_fd (char * module )
131+ {
132+ int fd , err ;
133+ __u32 id = 0 , len ;
134+ struct bpf_btf_info info ;
135+ char name [64 ];
136+
137+ while (true) {
138+ err = bpf_btf_get_next_id (id , & id );
139+ if (err )
140+ return -1 ;
141+
142+ fd = bpf_btf_get_fd_by_id (id );
143+ if (fd < 0 ) {
144+ if (errno == ENOENT )
145+ continue ;
146+ return -1 ;
147+ }
148+ len = sizeof (info );
149+ memset (& info , 0 , sizeof (info ));
150+ info .name = ptr_to_u64 (name );
151+ info .name_len = sizeof (name );
152+ err = bpf_btf_get_info_by_fd (fd , & info , & len );
153+ if (err ) {
154+ close (fd );
155+ return -1 ;
156+ }
157+ /* find target module BTF */
158+ if (!strcmp (name , module ))
159+ break ;
160+
161+ close (fd );
162+ }
163+
164+ return fd ;
165+ }
166+
167+ void test_libbpf_probe_kfuncs (void )
168+ {
169+ int ret , kfunc_id , fd ;
170+ char * kfunc = "bpf_cpumask_create" ;
171+ struct btf * vmlinux_btf = NULL ;
172+ struct btf * module_btf = NULL ;
173+
174+ vmlinux_btf = btf__parse ("/sys/kernel/btf/vmlinux" , NULL );
175+ if (!ASSERT_OK_PTR (vmlinux_btf , "btf_parse" ))
176+ return ;
177+
178+ kfunc_id = btf__find_by_name_kind (vmlinux_btf , kfunc , BTF_KIND_FUNC );
179+ if (!ASSERT_GT (kfunc_id , 0 , kfunc ))
180+ goto cleanup ;
181+
182+ /* prog BPF_PROG_TYPE_SYSCALL supports kfunc bpf_cpumask_create */
183+ ret = libbpf_probe_bpf_kfunc (BPF_PROG_TYPE_SYSCALL , kfunc_id , -1 , NULL );
184+ if (!ASSERT_EQ (ret , 1 , "kfunc in vmlinux support" ))
185+ goto cleanup ;
186+
187+ /* prog BPF_PROG_TYPE_KPROBE does not support kfunc bpf_cpumask_create */
188+ ret = libbpf_probe_bpf_kfunc (BPF_PROG_TYPE_KPROBE , kfunc_id , -1 , NULL );
189+ if (!ASSERT_EQ (ret , 0 , "kfunc in vmlinux not suuport" ))
190+ goto cleanup ;
191+
192+ ret = libbpf_probe_bpf_kfunc (BPF_PROG_TYPE_KPROBE , -1 , -1 , NULL );
193+ if (!ASSERT_EQ (ret , 0 , "invalid kfunc id:-1" ))
194+ goto cleanup ;
195+
196+ ret = libbpf_probe_bpf_kfunc (100000 , kfunc_id , -1 , NULL );
197+ if (!ASSERT_ERR (ret , "invalid prog type:100000" ))
198+ goto cleanup ;
199+
200+ if (!env .has_testmod )
201+ goto cleanup ;
202+
203+ module_btf = btf__load_module_btf ("bpf_testmod" , vmlinux_btf );
204+ if (!ASSERT_OK_PTR (module_btf , "load module BTF" ))
205+ goto cleanup ;
206+
207+ kfunc_id = btf__find_by_name (module_btf , "bpf_kfunc_call_test1" );
208+ if (!ASSERT_GT (kfunc_id , 0 , "func not found" ))
209+ goto cleanup ;
210+
211+ fd = module_btf_fd ("bpf_testmod" );
212+ if (!ASSERT_GE (fd , 0 , "module BTF fd" ))
213+ goto cleanup ;
214+
215+ /* prog BPF_PROG_TYPE_SYSCALL supports kfunc bpf_kfunc_call_test1 in bpf_testmod */
216+ ret = libbpf_probe_bpf_kfunc (BPF_PROG_TYPE_SYSCALL , kfunc_id , fd , NULL );
217+ if (!ASSERT_EQ (ret , 1 , "kfunc in module BTF support" ))
218+ goto cleanup_fd ;
219+
220+ /* prog BPF_PROG_TYPE_KPROBE does not support kfunc bpf_kfunc_call_test1
221+ * in bpf_testmod
222+ */
223+ ret = libbpf_probe_bpf_kfunc (BPF_PROG_TYPE_KPROBE , kfunc_id , fd , NULL );
224+ if (!ASSERT_EQ (ret , 0 , "kfunc in module BTF not support" ))
225+ goto cleanup_fd ;
226+
227+ ret = libbpf_probe_bpf_kfunc (BPF_PROG_TYPE_SYSCALL , -1 , fd , NULL );
228+ if (!ASSERT_EQ (ret , 0 , "invalid kfunc id in module BTF" ))
229+ goto cleanup_fd ;
230+
231+ ret = libbpf_probe_bpf_kfunc (BPF_PROG_TYPE_SYSCALL , kfunc_id , 100 , NULL );
232+ ASSERT_EQ (ret , 0 , "invalid BTF fd in module BTF" );
233+
234+ cleanup_fd :
235+ close (fd );
236+ cleanup :
237+ btf__free (vmlinux_btf );
238+ btf__free (module_btf );
239+ }
0 commit comments