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