xref: /linux/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1f7a11eecSJiri Olsa // SPDX-License-Identifier: GPL-2.0
2f7a11eecSJiri Olsa #include <test_progs.h>
3f7a11eecSJiri Olsa #include "kprobe_multi.skel.h"
4f7a11eecSJiri Olsa #include "trace_helpers.h"
55b6c7e5cSJiri Olsa #include "kprobe_multi_empty.skel.h"
67182e564SJiri Olsa #include "kprobe_multi_override.skel.h"
70983b169SJiri Olsa #include "kprobe_multi_session.skel.h"
8*a3a51133SJiri Olsa #include "kprobe_multi_session_cookie.skel.h"
95b6c7e5cSJiri Olsa #include "bpf/libbpf_internal.h"
105b6c7e5cSJiri Olsa #include "bpf/hashmap.h"
11f7a11eecSJiri Olsa 
kprobe_multi_test_run(struct kprobe_multi * skel,bool test_return)129271a0c7SJiri Olsa static void kprobe_multi_test_run(struct kprobe_multi *skel, bool test_return)
13f7a11eecSJiri Olsa {
14f7a11eecSJiri Olsa 	LIBBPF_OPTS(bpf_test_run_opts, topts);
15f7a11eecSJiri Olsa 	int err, prog_fd;
16f7a11eecSJiri Olsa 
17f7a11eecSJiri Olsa 	prog_fd = bpf_program__fd(skel->progs.trigger);
18f7a11eecSJiri Olsa 	err = bpf_prog_test_run_opts(prog_fd, &topts);
19f7a11eecSJiri Olsa 	ASSERT_OK(err, "test_run");
20f7a11eecSJiri Olsa 	ASSERT_EQ(topts.retval, 0, "test_run");
21f7a11eecSJiri Olsa 
22f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test1_result, 1, "kprobe_test1_result");
23f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test2_result, 1, "kprobe_test2_result");
24f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test3_result, 1, "kprobe_test3_result");
25f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test4_result, 1, "kprobe_test4_result");
26f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test5_result, 1, "kprobe_test5_result");
27f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test6_result, 1, "kprobe_test6_result");
28f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test7_result, 1, "kprobe_test7_result");
29f7a11eecSJiri Olsa 	ASSERT_EQ(skel->bss->kprobe_test8_result, 1, "kprobe_test8_result");
30f7a11eecSJiri Olsa 
319271a0c7SJiri Olsa 	if (test_return) {
32f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test1_result, 1, "kretprobe_test1_result");
33f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test2_result, 1, "kretprobe_test2_result");
34f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test3_result, 1, "kretprobe_test3_result");
35f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test4_result, 1, "kretprobe_test4_result");
36f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test5_result, 1, "kretprobe_test5_result");
37f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test6_result, 1, "kretprobe_test6_result");
38f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test7_result, 1, "kretprobe_test7_result");
39f7a11eecSJiri Olsa 		ASSERT_EQ(skel->bss->kretprobe_test8_result, 1, "kretprobe_test8_result");
40f7a11eecSJiri Olsa 	}
419271a0c7SJiri Olsa }
42f7a11eecSJiri Olsa 
test_skel_api(void)43f7a11eecSJiri Olsa static void test_skel_api(void)
44f7a11eecSJiri Olsa {
45f7a11eecSJiri Olsa 	struct kprobe_multi *skel = NULL;
46f7a11eecSJiri Olsa 	int err;
47f7a11eecSJiri Olsa 
48f7a11eecSJiri Olsa 	skel = kprobe_multi__open_and_load();
49f7a11eecSJiri Olsa 	if (!ASSERT_OK_PTR(skel, "kprobe_multi__open_and_load"))
50f7a11eecSJiri Olsa 		goto cleanup;
51f7a11eecSJiri Olsa 
52f7a11eecSJiri Olsa 	skel->bss->pid = getpid();
53f7a11eecSJiri Olsa 	err = kprobe_multi__attach(skel);
54f7a11eecSJiri Olsa 	if (!ASSERT_OK(err, "kprobe_multi__attach"))
55f7a11eecSJiri Olsa 		goto cleanup;
56f7a11eecSJiri Olsa 
579271a0c7SJiri Olsa 	kprobe_multi_test_run(skel, true);
58f7a11eecSJiri Olsa 
59f7a11eecSJiri Olsa cleanup:
60f7a11eecSJiri Olsa 	kprobe_multi__destroy(skel);
61f7a11eecSJiri Olsa }
62f7a11eecSJiri Olsa 
test_link_api(struct bpf_link_create_opts * opts)63f7a11eecSJiri Olsa static void test_link_api(struct bpf_link_create_opts *opts)
64f7a11eecSJiri Olsa {
65f7a11eecSJiri Olsa 	int prog_fd, link1_fd = -1, link2_fd = -1;
66f7a11eecSJiri Olsa 	struct kprobe_multi *skel = NULL;
67f7a11eecSJiri Olsa 
68f7a11eecSJiri Olsa 	skel = kprobe_multi__open_and_load();
69f7a11eecSJiri Olsa 	if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
70f7a11eecSJiri Olsa 		goto cleanup;
71f7a11eecSJiri Olsa 
72f7a11eecSJiri Olsa 	skel->bss->pid = getpid();
73f7a11eecSJiri Olsa 	prog_fd = bpf_program__fd(skel->progs.test_kprobe);
74f7a11eecSJiri Olsa 	link1_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, opts);
75f7a11eecSJiri Olsa 	if (!ASSERT_GE(link1_fd, 0, "link_fd"))
76f7a11eecSJiri Olsa 		goto cleanup;
77f7a11eecSJiri Olsa 
78f7a11eecSJiri Olsa 	opts->kprobe_multi.flags = BPF_F_KPROBE_MULTI_RETURN;
79f7a11eecSJiri Olsa 	prog_fd = bpf_program__fd(skel->progs.test_kretprobe);
80f7a11eecSJiri Olsa 	link2_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, opts);
81f7a11eecSJiri Olsa 	if (!ASSERT_GE(link2_fd, 0, "link_fd"))
82f7a11eecSJiri Olsa 		goto cleanup;
83f7a11eecSJiri Olsa 
849271a0c7SJiri Olsa 	kprobe_multi_test_run(skel, true);
85f7a11eecSJiri Olsa 
86f7a11eecSJiri Olsa cleanup:
87f7a11eecSJiri Olsa 	if (link1_fd != -1)
88f7a11eecSJiri Olsa 		close(link1_fd);
89f7a11eecSJiri Olsa 	if (link2_fd != -1)
90f7a11eecSJiri Olsa 		close(link2_fd);
91f7a11eecSJiri Olsa 	kprobe_multi__destroy(skel);
92f7a11eecSJiri Olsa }
93f7a11eecSJiri Olsa 
94f7a11eecSJiri Olsa #define GET_ADDR(__sym, __addr) ({					\
95f7a11eecSJiri Olsa 	__addr = ksym_get_addr(__sym);					\
96f7a11eecSJiri Olsa 	if (!ASSERT_NEQ(__addr, 0, "kallsyms load failed for " #__sym))	\
97f7a11eecSJiri Olsa 		return;							\
98f7a11eecSJiri Olsa })
99f7a11eecSJiri Olsa 
test_link_api_addrs(void)100f7a11eecSJiri Olsa static void test_link_api_addrs(void)
101f7a11eecSJiri Olsa {
102f7a11eecSJiri Olsa 	LIBBPF_OPTS(bpf_link_create_opts, opts);
103f7a11eecSJiri Olsa 	unsigned long long addrs[8];
104f7a11eecSJiri Olsa 
105f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test1", addrs[0]);
106f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test2", addrs[1]);
107f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test3", addrs[2]);
108f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test4", addrs[3]);
109f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test5", addrs[4]);
110f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test6", addrs[5]);
111f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test7", addrs[6]);
112f7a11eecSJiri Olsa 	GET_ADDR("bpf_fentry_test8", addrs[7]);
113f7a11eecSJiri Olsa 
114f7a11eecSJiri Olsa 	opts.kprobe_multi.addrs = (const unsigned long*) addrs;
115f7a11eecSJiri Olsa 	opts.kprobe_multi.cnt = ARRAY_SIZE(addrs);
116f7a11eecSJiri Olsa 	test_link_api(&opts);
117f7a11eecSJiri Olsa }
118f7a11eecSJiri Olsa 
test_link_api_syms(void)119f7a11eecSJiri Olsa static void test_link_api_syms(void)
120f7a11eecSJiri Olsa {
121f7a11eecSJiri Olsa 	LIBBPF_OPTS(bpf_link_create_opts, opts);
122f7a11eecSJiri Olsa 	const char *syms[8] = {
123f7a11eecSJiri Olsa 		"bpf_fentry_test1",
124f7a11eecSJiri Olsa 		"bpf_fentry_test2",
125f7a11eecSJiri Olsa 		"bpf_fentry_test3",
126f7a11eecSJiri Olsa 		"bpf_fentry_test4",
127f7a11eecSJiri Olsa 		"bpf_fentry_test5",
128f7a11eecSJiri Olsa 		"bpf_fentry_test6",
129f7a11eecSJiri Olsa 		"bpf_fentry_test7",
130f7a11eecSJiri Olsa 		"bpf_fentry_test8",
131f7a11eecSJiri Olsa 	};
132f7a11eecSJiri Olsa 
133f7a11eecSJiri Olsa 	opts.kprobe_multi.syms = syms;
134f7a11eecSJiri Olsa 	opts.kprobe_multi.cnt = ARRAY_SIZE(syms);
135f7a11eecSJiri Olsa 	test_link_api(&opts);
136f7a11eecSJiri Olsa }
137f7a11eecSJiri Olsa 
1389271a0c7SJiri Olsa static void
test_attach_api(const char * pattern,struct bpf_kprobe_multi_opts * opts)1399271a0c7SJiri Olsa test_attach_api(const char *pattern, struct bpf_kprobe_multi_opts *opts)
1409271a0c7SJiri Olsa {
1419271a0c7SJiri Olsa 	struct bpf_link *link1 = NULL, *link2 = NULL;
1429271a0c7SJiri Olsa 	struct kprobe_multi *skel = NULL;
1439271a0c7SJiri Olsa 
1449271a0c7SJiri Olsa 	skel = kprobe_multi__open_and_load();
1459271a0c7SJiri Olsa 	if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
1469271a0c7SJiri Olsa 		goto cleanup;
1479271a0c7SJiri Olsa 
1489271a0c7SJiri Olsa 	skel->bss->pid = getpid();
14932c03c49SAndrii Nakryiko 	link1 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
1509271a0c7SJiri Olsa 						      pattern, opts);
1519271a0c7SJiri Olsa 	if (!ASSERT_OK_PTR(link1, "bpf_program__attach_kprobe_multi_opts"))
1529271a0c7SJiri Olsa 		goto cleanup;
1539271a0c7SJiri Olsa 
1549271a0c7SJiri Olsa 	if (opts) {
1559271a0c7SJiri Olsa 		opts->retprobe = true;
15632c03c49SAndrii Nakryiko 		link2 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kretprobe_manual,
1579271a0c7SJiri Olsa 							      pattern, opts);
1589271a0c7SJiri Olsa 		if (!ASSERT_OK_PTR(link2, "bpf_program__attach_kprobe_multi_opts"))
1599271a0c7SJiri Olsa 			goto cleanup;
1609271a0c7SJiri Olsa 	}
1619271a0c7SJiri Olsa 
1629271a0c7SJiri Olsa 	kprobe_multi_test_run(skel, !!opts);
1639271a0c7SJiri Olsa 
1649271a0c7SJiri Olsa cleanup:
1659271a0c7SJiri Olsa 	bpf_link__destroy(link2);
1669271a0c7SJiri Olsa 	bpf_link__destroy(link1);
1679271a0c7SJiri Olsa 	kprobe_multi__destroy(skel);
1689271a0c7SJiri Olsa }
1699271a0c7SJiri Olsa 
test_attach_api_pattern(void)1709271a0c7SJiri Olsa static void test_attach_api_pattern(void)
1719271a0c7SJiri Olsa {
1729271a0c7SJiri Olsa 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
1739271a0c7SJiri Olsa 
1749271a0c7SJiri Olsa 	test_attach_api("bpf_fentry_test*", &opts);
1759271a0c7SJiri Olsa 	test_attach_api("bpf_fentry_test?", NULL);
1769271a0c7SJiri Olsa }
1779271a0c7SJiri Olsa 
test_attach_api_addrs(void)1789271a0c7SJiri Olsa static void test_attach_api_addrs(void)
1799271a0c7SJiri Olsa {
1809271a0c7SJiri Olsa 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
1819271a0c7SJiri Olsa 	unsigned long long addrs[8];
1829271a0c7SJiri Olsa 
1839271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test1", addrs[0]);
1849271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test2", addrs[1]);
1859271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test3", addrs[2]);
1869271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test4", addrs[3]);
1879271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test5", addrs[4]);
1889271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test6", addrs[5]);
1899271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test7", addrs[6]);
1909271a0c7SJiri Olsa 	GET_ADDR("bpf_fentry_test8", addrs[7]);
1919271a0c7SJiri Olsa 
1929271a0c7SJiri Olsa 	opts.addrs = (const unsigned long *) addrs;
1939271a0c7SJiri Olsa 	opts.cnt = ARRAY_SIZE(addrs);
1949271a0c7SJiri Olsa 	test_attach_api(NULL, &opts);
1959271a0c7SJiri Olsa }
1969271a0c7SJiri Olsa 
test_attach_api_syms(void)1979271a0c7SJiri Olsa static void test_attach_api_syms(void)
1989271a0c7SJiri Olsa {
1999271a0c7SJiri Olsa 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
2009271a0c7SJiri Olsa 	const char *syms[8] = {
2019271a0c7SJiri Olsa 		"bpf_fentry_test1",
2029271a0c7SJiri Olsa 		"bpf_fentry_test2",
2039271a0c7SJiri Olsa 		"bpf_fentry_test3",
2049271a0c7SJiri Olsa 		"bpf_fentry_test4",
2059271a0c7SJiri Olsa 		"bpf_fentry_test5",
2069271a0c7SJiri Olsa 		"bpf_fentry_test6",
2079271a0c7SJiri Olsa 		"bpf_fentry_test7",
2089271a0c7SJiri Olsa 		"bpf_fentry_test8",
2099271a0c7SJiri Olsa 	};
2109271a0c7SJiri Olsa 
2119271a0c7SJiri Olsa 	opts.syms = syms;
2129271a0c7SJiri Olsa 	opts.cnt = ARRAY_SIZE(syms);
2139271a0c7SJiri Olsa 	test_attach_api(NULL, &opts);
2149271a0c7SJiri Olsa }
2159271a0c7SJiri Olsa 
test_attach_api_fails(void)2169271a0c7SJiri Olsa static void test_attach_api_fails(void)
2179271a0c7SJiri Olsa {
2189271a0c7SJiri Olsa 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
2199271a0c7SJiri Olsa 	struct kprobe_multi *skel = NULL;
2209271a0c7SJiri Olsa 	struct bpf_link *link = NULL;
2219271a0c7SJiri Olsa 	unsigned long long addrs[2];
2229271a0c7SJiri Olsa 	const char *syms[2] = {
2239271a0c7SJiri Olsa 		"bpf_fentry_test1",
2249271a0c7SJiri Olsa 		"bpf_fentry_test2",
2259271a0c7SJiri Olsa 	};
2269271a0c7SJiri Olsa 	__u64 cookies[2];
22700cdcd29SHou Tao 	int saved_error;
2289271a0c7SJiri Olsa 
2299271a0c7SJiri Olsa 	addrs[0] = ksym_get_addr("bpf_fentry_test1");
2309271a0c7SJiri Olsa 	addrs[1] = ksym_get_addr("bpf_fentry_test2");
2319271a0c7SJiri Olsa 
2329271a0c7SJiri Olsa 	if (!ASSERT_FALSE(!addrs[0] || !addrs[1], "ksym_get_addr"))
2339271a0c7SJiri Olsa 		goto cleanup;
2349271a0c7SJiri Olsa 
2359271a0c7SJiri Olsa 	skel = kprobe_multi__open_and_load();
2369271a0c7SJiri Olsa 	if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
2379271a0c7SJiri Olsa 		goto cleanup;
2389271a0c7SJiri Olsa 
2399271a0c7SJiri Olsa 	skel->bss->pid = getpid();
2409271a0c7SJiri Olsa 
2419271a0c7SJiri Olsa 	/* fail_1 - pattern and opts NULL */
24232c03c49SAndrii Nakryiko 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
2439271a0c7SJiri Olsa 						     NULL, NULL);
24400cdcd29SHou Tao 	saved_error = -errno;
2459271a0c7SJiri Olsa 	if (!ASSERT_ERR_PTR(link, "fail_1"))
2469271a0c7SJiri Olsa 		goto cleanup;
2479271a0c7SJiri Olsa 
24800cdcd29SHou Tao 	if (!ASSERT_EQ(saved_error, -EINVAL, "fail_1_error"))
2499271a0c7SJiri Olsa 		goto cleanup;
2509271a0c7SJiri Olsa 
2519271a0c7SJiri Olsa 	/* fail_2 - both addrs and syms set */
2529271a0c7SJiri Olsa 	opts.addrs = (const unsigned long *) addrs;
2539271a0c7SJiri Olsa 	opts.syms = syms;
2549271a0c7SJiri Olsa 	opts.cnt = ARRAY_SIZE(syms);
2559271a0c7SJiri Olsa 	opts.cookies = NULL;
2569271a0c7SJiri Olsa 
25732c03c49SAndrii Nakryiko 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
2589271a0c7SJiri Olsa 						     NULL, &opts);
25900cdcd29SHou Tao 	saved_error = -errno;
2609271a0c7SJiri Olsa 	if (!ASSERT_ERR_PTR(link, "fail_2"))
2619271a0c7SJiri Olsa 		goto cleanup;
2629271a0c7SJiri Olsa 
26300cdcd29SHou Tao 	if (!ASSERT_EQ(saved_error, -EINVAL, "fail_2_error"))
2649271a0c7SJiri Olsa 		goto cleanup;
2659271a0c7SJiri Olsa 
2669271a0c7SJiri Olsa 	/* fail_3 - pattern and addrs set */
2679271a0c7SJiri Olsa 	opts.addrs = (const unsigned long *) addrs;
2689271a0c7SJiri Olsa 	opts.syms = NULL;
2699271a0c7SJiri Olsa 	opts.cnt = ARRAY_SIZE(syms);
2709271a0c7SJiri Olsa 	opts.cookies = NULL;
2719271a0c7SJiri Olsa 
27232c03c49SAndrii Nakryiko 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
2739271a0c7SJiri Olsa 						     "ksys_*", &opts);
27400cdcd29SHou Tao 	saved_error = -errno;
2759271a0c7SJiri Olsa 	if (!ASSERT_ERR_PTR(link, "fail_3"))
2769271a0c7SJiri Olsa 		goto cleanup;
2779271a0c7SJiri Olsa 
27800cdcd29SHou Tao 	if (!ASSERT_EQ(saved_error, -EINVAL, "fail_3_error"))
2799271a0c7SJiri Olsa 		goto cleanup;
2809271a0c7SJiri Olsa 
2819271a0c7SJiri Olsa 	/* fail_4 - pattern and cnt set */
2829271a0c7SJiri Olsa 	opts.addrs = NULL;
2839271a0c7SJiri Olsa 	opts.syms = NULL;
2849271a0c7SJiri Olsa 	opts.cnt = ARRAY_SIZE(syms);
2859271a0c7SJiri Olsa 	opts.cookies = NULL;
2869271a0c7SJiri Olsa 
28732c03c49SAndrii Nakryiko 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
2889271a0c7SJiri Olsa 						     "ksys_*", &opts);
28900cdcd29SHou Tao 	saved_error = -errno;
2909271a0c7SJiri Olsa 	if (!ASSERT_ERR_PTR(link, "fail_4"))
2919271a0c7SJiri Olsa 		goto cleanup;
2929271a0c7SJiri Olsa 
29300cdcd29SHou Tao 	if (!ASSERT_EQ(saved_error, -EINVAL, "fail_4_error"))
2949271a0c7SJiri Olsa 		goto cleanup;
2959271a0c7SJiri Olsa 
2969271a0c7SJiri Olsa 	/* fail_5 - pattern and cookies */
2979271a0c7SJiri Olsa 	opts.addrs = NULL;
2989271a0c7SJiri Olsa 	opts.syms = NULL;
2999271a0c7SJiri Olsa 	opts.cnt = 0;
3009271a0c7SJiri Olsa 	opts.cookies = cookies;
3019271a0c7SJiri Olsa 
30232c03c49SAndrii Nakryiko 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
3039271a0c7SJiri Olsa 						     "ksys_*", &opts);
30400cdcd29SHou Tao 	saved_error = -errno;
3059271a0c7SJiri Olsa 	if (!ASSERT_ERR_PTR(link, "fail_5"))
3069271a0c7SJiri Olsa 		goto cleanup;
3079271a0c7SJiri Olsa 
30800cdcd29SHou Tao 	if (!ASSERT_EQ(saved_error, -EINVAL, "fail_5_error"))
3099271a0c7SJiri Olsa 		goto cleanup;
3109271a0c7SJiri Olsa 
3111467affdSHou Tao 	/* fail_6 - abnormal cnt */
3121467affdSHou Tao 	opts.addrs = (const unsigned long *) addrs;
3131467affdSHou Tao 	opts.syms = NULL;
3141467affdSHou Tao 	opts.cnt = INT_MAX;
3151467affdSHou Tao 	opts.cookies = NULL;
3161467affdSHou Tao 
3171467affdSHou Tao 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
3181467affdSHou Tao 						     NULL, &opts);
3191467affdSHou Tao 	saved_error = -errno;
3201467affdSHou Tao 	if (!ASSERT_ERR_PTR(link, "fail_6"))
3211467affdSHou Tao 		goto cleanup;
3221467affdSHou Tao 
3231467affdSHou Tao 	if (!ASSERT_EQ(saved_error, -E2BIG, "fail_6_error"))
3241467affdSHou Tao 		goto cleanup;
3251467affdSHou Tao 
3269271a0c7SJiri Olsa cleanup:
3279271a0c7SJiri Olsa 	bpf_link__destroy(link);
3289271a0c7SJiri Olsa 	kprobe_multi__destroy(skel);
3299271a0c7SJiri Olsa }
3309271a0c7SJiri Olsa 
test_session_skel_api(void)3310983b169SJiri Olsa static void test_session_skel_api(void)
3320983b169SJiri Olsa {
3330983b169SJiri Olsa 	struct kprobe_multi_session *skel = NULL;
3340983b169SJiri Olsa 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
3350983b169SJiri Olsa 	LIBBPF_OPTS(bpf_test_run_opts, topts);
3360983b169SJiri Olsa 	struct bpf_link *link = NULL;
3370983b169SJiri Olsa 	int i, err, prog_fd;
3380983b169SJiri Olsa 
3390983b169SJiri Olsa 	skel = kprobe_multi_session__open_and_load();
3400983b169SJiri Olsa 	if (!ASSERT_OK_PTR(skel, "kprobe_multi_session__open_and_load"))
3410983b169SJiri Olsa 		return;
3420983b169SJiri Olsa 
3430983b169SJiri Olsa 	skel->bss->pid = getpid();
3440983b169SJiri Olsa 
3450983b169SJiri Olsa 	err = kprobe_multi_session__attach(skel);
3460983b169SJiri Olsa 	if (!ASSERT_OK(err, " kprobe_multi_session__attach"))
3470983b169SJiri Olsa 		goto cleanup;
3480983b169SJiri Olsa 
3490983b169SJiri Olsa 	prog_fd = bpf_program__fd(skel->progs.trigger);
3500983b169SJiri Olsa 	err = bpf_prog_test_run_opts(prog_fd, &topts);
3510983b169SJiri Olsa 	ASSERT_OK(err, "test_run");
3520983b169SJiri Olsa 	ASSERT_EQ(topts.retval, 0, "test_run");
3530983b169SJiri Olsa 
3540983b169SJiri Olsa 	/* bpf_fentry_test1-4 trigger return probe, result is 2 */
3550983b169SJiri Olsa 	for (i = 0; i < 4; i++)
3560983b169SJiri Olsa 		ASSERT_EQ(skel->bss->kprobe_session_result[i], 2, "kprobe_session_result");
3570983b169SJiri Olsa 
3580983b169SJiri Olsa 	/* bpf_fentry_test5-8 trigger only entry probe, result is 1 */
3590983b169SJiri Olsa 	for (i = 4; i < 8; i++)
3600983b169SJiri Olsa 		ASSERT_EQ(skel->bss->kprobe_session_result[i], 1, "kprobe_session_result");
3610983b169SJiri Olsa 
3620983b169SJiri Olsa cleanup:
3630983b169SJiri Olsa 	bpf_link__destroy(link);
3640983b169SJiri Olsa 	kprobe_multi_session__destroy(skel);
3650983b169SJiri Olsa }
3660983b169SJiri Olsa 
test_session_cookie_skel_api(void)367*a3a51133SJiri Olsa static void test_session_cookie_skel_api(void)
368*a3a51133SJiri Olsa {
369*a3a51133SJiri Olsa 	struct kprobe_multi_session_cookie *skel = NULL;
370*a3a51133SJiri Olsa 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
371*a3a51133SJiri Olsa 	LIBBPF_OPTS(bpf_test_run_opts, topts);
372*a3a51133SJiri Olsa 	struct bpf_link *link = NULL;
373*a3a51133SJiri Olsa 	int err, prog_fd;
374*a3a51133SJiri Olsa 
375*a3a51133SJiri Olsa 	skel = kprobe_multi_session_cookie__open_and_load();
376*a3a51133SJiri Olsa 	if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
377*a3a51133SJiri Olsa 		return;
378*a3a51133SJiri Olsa 
379*a3a51133SJiri Olsa 	skel->bss->pid = getpid();
380*a3a51133SJiri Olsa 
381*a3a51133SJiri Olsa 	err = kprobe_multi_session_cookie__attach(skel);
382*a3a51133SJiri Olsa 	if (!ASSERT_OK(err, " kprobe_multi_wrapper__attach"))
383*a3a51133SJiri Olsa 		goto cleanup;
384*a3a51133SJiri Olsa 
385*a3a51133SJiri Olsa 	prog_fd = bpf_program__fd(skel->progs.trigger);
386*a3a51133SJiri Olsa 	err = bpf_prog_test_run_opts(prog_fd, &topts);
387*a3a51133SJiri Olsa 	ASSERT_OK(err, "test_run");
388*a3a51133SJiri Olsa 	ASSERT_EQ(topts.retval, 0, "test_run");
389*a3a51133SJiri Olsa 
390*a3a51133SJiri Olsa 	ASSERT_EQ(skel->bss->test_kprobe_1_result, 1, "test_kprobe_1_result");
391*a3a51133SJiri Olsa 	ASSERT_EQ(skel->bss->test_kprobe_2_result, 2, "test_kprobe_2_result");
392*a3a51133SJiri Olsa 	ASSERT_EQ(skel->bss->test_kprobe_3_result, 3, "test_kprobe_3_result");
393*a3a51133SJiri Olsa 
394*a3a51133SJiri Olsa cleanup:
395*a3a51133SJiri Olsa 	bpf_link__destroy(link);
396*a3a51133SJiri Olsa 	kprobe_multi_session_cookie__destroy(skel);
397*a3a51133SJiri Olsa }
398*a3a51133SJiri Olsa 
symbol_hash(long key,void * ctx __maybe_unused)399c302378bSEduard Zingerman static size_t symbol_hash(long key, void *ctx __maybe_unused)
4005b6c7e5cSJiri Olsa {
4015b6c7e5cSJiri Olsa 	return str_hash((const char *) key);
4025b6c7e5cSJiri Olsa }
4035b6c7e5cSJiri Olsa 
symbol_equal(long key1,long key2,void * ctx __maybe_unused)404c302378bSEduard Zingerman static bool symbol_equal(long key1, long key2, void *ctx __maybe_unused)
4055b6c7e5cSJiri Olsa {
4065b6c7e5cSJiri Olsa 	return strcmp((const char *) key1, (const char *) key2) == 0;
4075b6c7e5cSJiri Olsa }
4085b6c7e5cSJiri Olsa 
is_invalid_entry(char * buf,bool kernel)409d1320649SYonghong Song static bool is_invalid_entry(char *buf, bool kernel)
410d1320649SYonghong Song {
411d1320649SYonghong Song 	if (kernel && strchr(buf, '['))
412d1320649SYonghong Song 		return true;
413d1320649SYonghong Song 	if (!kernel && !strchr(buf, '['))
414d1320649SYonghong Song 		return true;
415d1320649SYonghong Song 	return false;
416d1320649SYonghong Song }
417d1320649SYonghong Song 
skip_entry(char * name)418d1320649SYonghong Song static bool skip_entry(char *name)
419d1320649SYonghong Song {
420d1320649SYonghong Song 	/*
421d1320649SYonghong Song 	 * We attach to almost all kernel functions and some of them
422d1320649SYonghong Song 	 * will cause 'suspicious RCU usage' when fprobe is attached
423d1320649SYonghong Song 	 * to them. Filter out the current culprits - arch_cpu_idle
424d1320649SYonghong Song 	 * default_idle and rcu_* functions.
425d1320649SYonghong Song 	 */
426d1320649SYonghong Song 	if (!strcmp(name, "arch_cpu_idle"))
427d1320649SYonghong Song 		return true;
428d1320649SYonghong Song 	if (!strcmp(name, "default_idle"))
429d1320649SYonghong Song 		return true;
430d1320649SYonghong Song 	if (!strncmp(name, "rcu_", 4))
431d1320649SYonghong Song 		return true;
432d1320649SYonghong Song 	if (!strcmp(name, "bpf_dispatcher_xdp_func"))
433d1320649SYonghong Song 		return true;
434d1320649SYonghong Song 	if (!strncmp(name, "__ftrace_invalid_address__",
435d1320649SYonghong Song 		     sizeof("__ftrace_invalid_address__") - 1))
436d1320649SYonghong Song 		return true;
437d1320649SYonghong Song 	return false;
438d1320649SYonghong Song }
439d1320649SYonghong Song 
4409edaafadSYonghong Song /* Do comparision by ignoring '.llvm.<hash>' suffixes. */
compare_name(const char * name1,const char * name2)4419edaafadSYonghong Song static int compare_name(const char *name1, const char *name2)
4429edaafadSYonghong Song {
4439edaafadSYonghong Song 	const char *res1, *res2;
4449edaafadSYonghong Song 	int len1, len2;
4459edaafadSYonghong Song 
4469edaafadSYonghong Song 	res1 = strstr(name1, ".llvm.");
4479edaafadSYonghong Song 	res2 = strstr(name2, ".llvm.");
4489edaafadSYonghong Song 	len1 = res1 ? res1 - name1 : strlen(name1);
4499edaafadSYonghong Song 	len2 = res2 ? res2 - name2 : strlen(name2);
4509edaafadSYonghong Song 
4519edaafadSYonghong Song 	if (len1 == len2)
4529edaafadSYonghong Song 		return strncmp(name1, name2, len1);
4539edaafadSYonghong Song 	if (len1 < len2)
4549edaafadSYonghong Song 		return strncmp(name1, name2, len1) <= 0 ? -1 : 1;
4559edaafadSYonghong Song 	return strncmp(name1, name2, len2) >= 0 ? 1 : -1;
4569edaafadSYonghong Song }
4579edaafadSYonghong Song 
load_kallsyms_compare(const void * p1,const void * p2)4589edaafadSYonghong Song static int load_kallsyms_compare(const void *p1, const void *p2)
4599edaafadSYonghong Song {
4609edaafadSYonghong Song 	return compare_name(((const struct ksym *)p1)->name, ((const struct ksym *)p2)->name);
4619edaafadSYonghong Song }
4629edaafadSYonghong Song 
search_kallsyms_compare(const void * p1,const struct ksym * p2)4639edaafadSYonghong Song static int search_kallsyms_compare(const void *p1, const struct ksym *p2)
4649edaafadSYonghong Song {
4659edaafadSYonghong Song 	return compare_name(p1, p2->name);
4669edaafadSYonghong Song }
4679edaafadSYonghong Song 
get_syms(char *** symsp,size_t * cntp,bool kernel)468edac4b5bSJiri Olsa static int get_syms(char ***symsp, size_t *cntp, bool kernel)
4695b6c7e5cSJiri Olsa {
4709edaafadSYonghong Song 	size_t cap = 0, cnt = 0;
4719edaafadSYonghong Song 	char *name = NULL, *ksym_name, **syms = NULL;
4725b6c7e5cSJiri Olsa 	struct hashmap *map;
4739edaafadSYonghong Song 	struct ksyms *ksyms;
4749edaafadSYonghong Song 	struct ksym *ks;
4755b6c7e5cSJiri Olsa 	char buf[256];
4765b6c7e5cSJiri Olsa 	FILE *f;
477c46a1220SAndrii Nakryiko 	int err = 0;
4785b6c7e5cSJiri Olsa 
4799edaafadSYonghong Song 	ksyms = load_kallsyms_custom_local(load_kallsyms_compare);
4809edaafadSYonghong Song 	if (!ASSERT_OK_PTR(ksyms, "load_kallsyms_custom_local"))
4819edaafadSYonghong Song 		return -EINVAL;
4829edaafadSYonghong Song 
4835b6c7e5cSJiri Olsa 	/*
4845b6c7e5cSJiri Olsa 	 * The available_filter_functions contains many duplicates,
4855b6c7e5cSJiri Olsa 	 * but other than that all symbols are usable in kprobe multi
4865b6c7e5cSJiri Olsa 	 * interface.
4875b6c7e5cSJiri Olsa 	 * Filtering out duplicates by using hashmap__add, which won't
4885b6c7e5cSJiri Olsa 	 * add existing entry.
4895b6c7e5cSJiri Olsa 	 */
490ab4c15feSRoss Zwisler 
491ab4c15feSRoss Zwisler 	if (access("/sys/kernel/tracing/trace", F_OK) == 0)
492ab4c15feSRoss Zwisler 		f = fopen("/sys/kernel/tracing/available_filter_functions", "r");
493ab4c15feSRoss Zwisler 	else
4945b6c7e5cSJiri Olsa 		f = fopen("/sys/kernel/debug/tracing/available_filter_functions", "r");
495ab4c15feSRoss Zwisler 
4965b6c7e5cSJiri Olsa 	if (!f)
4975b6c7e5cSJiri Olsa 		return -EINVAL;
4985b6c7e5cSJiri Olsa 
4995b6c7e5cSJiri Olsa 	map = hashmap__new(symbol_hash, symbol_equal, NULL);
500fd0ad6f1SYonghong Song 	if (IS_ERR(map)) {
501fd0ad6f1SYonghong Song 		err = libbpf_get_error(map);
5025b6c7e5cSJiri Olsa 		goto error;
503fd0ad6f1SYonghong Song 	}
5045b6c7e5cSJiri Olsa 
5055b6c7e5cSJiri Olsa 	while (fgets(buf, sizeof(buf), f)) {
506d1320649SYonghong Song 		if (is_invalid_entry(buf, kernel))
5075b6c7e5cSJiri Olsa 			continue;
5086d2e21dcSXu Kuohai 
5096d2e21dcSXu Kuohai 		free(name);
5105b6c7e5cSJiri Olsa 		if (sscanf(buf, "%ms$*[^\n]\n", &name) != 1)
5115b6c7e5cSJiri Olsa 			continue;
512d1320649SYonghong Song 		if (skip_entry(name))
51373006702SJiri Olsa 			continue;
5146d2e21dcSXu Kuohai 
5159edaafadSYonghong Song 		ks = search_kallsyms_custom_local(ksyms, name, search_kallsyms_compare);
5169edaafadSYonghong Song 		if (!ks) {
5179edaafadSYonghong Song 			err = -EINVAL;
5189edaafadSYonghong Song 			goto error;
5199edaafadSYonghong Song 		}
5209edaafadSYonghong Song 
5219edaafadSYonghong Song 		ksym_name = ks->name;
5229edaafadSYonghong Song 		err = hashmap__add(map, ksym_name, 0);
523c4d3b488SManu Bretelle 		if (err == -EEXIST) {
524c4d3b488SManu Bretelle 			err = 0;
5255b6c7e5cSJiri Olsa 			continue;
526c4d3b488SManu Bretelle 		}
5276d2e21dcSXu Kuohai 		if (err)
5285b6c7e5cSJiri Olsa 			goto error;
5296d2e21dcSXu Kuohai 
5305b6c7e5cSJiri Olsa 		err = libbpf_ensure_mem((void **) &syms, &cap,
5315b6c7e5cSJiri Olsa 					sizeof(*syms), cnt + 1);
5326d2e21dcSXu Kuohai 		if (err)
5335b6c7e5cSJiri Olsa 			goto error;
5346d2e21dcSXu Kuohai 
5359edaafadSYonghong Song 		syms[cnt++] = ksym_name;
5365b6c7e5cSJiri Olsa 	}
5375b6c7e5cSJiri Olsa 
5385b6c7e5cSJiri Olsa 	*symsp = syms;
5395b6c7e5cSJiri Olsa 	*cntp = cnt;
5405b6c7e5cSJiri Olsa 
5415b6c7e5cSJiri Olsa error:
5426d2e21dcSXu Kuohai 	free(name);
5435b6c7e5cSJiri Olsa 	fclose(f);
5445b6c7e5cSJiri Olsa 	hashmap__free(map);
5459edaafadSYonghong Song 	if (err)
5465b6c7e5cSJiri Olsa 		free(syms);
5475b6c7e5cSJiri Olsa 	return err;
5485b6c7e5cSJiri Olsa }
5495b6c7e5cSJiri Olsa 
get_addrs(unsigned long ** addrsp,size_t * cntp,bool kernel)5506302bdebSYonghong Song static int get_addrs(unsigned long **addrsp, size_t *cntp, bool kernel)
5516302bdebSYonghong Song {
5526302bdebSYonghong Song 	unsigned long *addr, *addrs, *tmp_addrs;
5536302bdebSYonghong Song 	int err = 0, max_cnt, inc_cnt;
5546302bdebSYonghong Song 	char *name = NULL;
5556302bdebSYonghong Song 	size_t cnt = 0;
5566302bdebSYonghong Song 	char buf[256];
5576302bdebSYonghong Song 	FILE *f;
5586302bdebSYonghong Song 
5596302bdebSYonghong Song 	if (access("/sys/kernel/tracing/trace", F_OK) == 0)
5606302bdebSYonghong Song 		f = fopen("/sys/kernel/tracing/available_filter_functions_addrs", "r");
5616302bdebSYonghong Song 	else
5626302bdebSYonghong Song 		f = fopen("/sys/kernel/debug/tracing/available_filter_functions_addrs", "r");
5636302bdebSYonghong Song 
5646302bdebSYonghong Song 	if (!f)
5656302bdebSYonghong Song 		return -ENOENT;
5666302bdebSYonghong Song 
5676302bdebSYonghong Song 	/* In my local setup, the number of entries is 50k+ so Let us initially
5686302bdebSYonghong Song 	 * allocate space to hold 64k entries. If 64k is not enough, incrementally
5696302bdebSYonghong Song 	 * increase 1k each time.
5706302bdebSYonghong Song 	 */
5716302bdebSYonghong Song 	max_cnt = 65536;
5726302bdebSYonghong Song 	inc_cnt = 1024;
5736302bdebSYonghong Song 	addrs = malloc(max_cnt * sizeof(long));
5746302bdebSYonghong Song 	if (addrs == NULL) {
5756302bdebSYonghong Song 		err = -ENOMEM;
5766302bdebSYonghong Song 		goto error;
5776302bdebSYonghong Song 	}
5786302bdebSYonghong Song 
5796302bdebSYonghong Song 	while (fgets(buf, sizeof(buf), f)) {
5806302bdebSYonghong Song 		if (is_invalid_entry(buf, kernel))
5816302bdebSYonghong Song 			continue;
5826302bdebSYonghong Song 
5836302bdebSYonghong Song 		free(name);
5846302bdebSYonghong Song 		if (sscanf(buf, "%p %ms$*[^\n]\n", &addr, &name) != 2)
5856302bdebSYonghong Song 			continue;
5866302bdebSYonghong Song 		if (skip_entry(name))
5876302bdebSYonghong Song 			continue;
5886302bdebSYonghong Song 
5896302bdebSYonghong Song 		if (cnt == max_cnt) {
5906302bdebSYonghong Song 			max_cnt += inc_cnt;
5916302bdebSYonghong Song 			tmp_addrs = realloc(addrs, max_cnt);
5926302bdebSYonghong Song 			if (!tmp_addrs) {
5936302bdebSYonghong Song 				err = -ENOMEM;
5946302bdebSYonghong Song 				goto error;
5956302bdebSYonghong Song 			}
5966302bdebSYonghong Song 			addrs = tmp_addrs;
5976302bdebSYonghong Song 		}
5986302bdebSYonghong Song 
5996302bdebSYonghong Song 		addrs[cnt++] = (unsigned long)addr;
6006302bdebSYonghong Song 	}
6016302bdebSYonghong Song 
6026302bdebSYonghong Song 	*addrsp = addrs;
6036302bdebSYonghong Song 	*cntp = cnt;
6046302bdebSYonghong Song 
6056302bdebSYonghong Song error:
6066302bdebSYonghong Song 	free(name);
6076302bdebSYonghong Song 	fclose(f);
6086302bdebSYonghong Song 	if (err)
6096302bdebSYonghong Song 		free(addrs);
6106302bdebSYonghong Song 	return err;
6116302bdebSYonghong Song }
6126302bdebSYonghong Song 
do_bench_test(struct kprobe_multi_empty * skel,struct bpf_kprobe_multi_opts * opts)613d1320649SYonghong Song static void do_bench_test(struct kprobe_multi_empty *skel, struct bpf_kprobe_multi_opts *opts)
6145b6c7e5cSJiri Olsa {
6155b6c7e5cSJiri Olsa 	long attach_start_ns, attach_end_ns;
6165b6c7e5cSJiri Olsa 	long detach_start_ns, detach_end_ns;
6175b6c7e5cSJiri Olsa 	double attach_delta, detach_delta;
6185b6c7e5cSJiri Olsa 	struct bpf_link *link = NULL;
619d1320649SYonghong Song 
620d1320649SYonghong Song 	attach_start_ns = get_time_ns();
621d1320649SYonghong Song 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_empty,
622d1320649SYonghong Song 						     NULL, opts);
623d1320649SYonghong Song 	attach_end_ns = get_time_ns();
624d1320649SYonghong Song 
625d1320649SYonghong Song 	if (!ASSERT_OK_PTR(link, "bpf_program__attach_kprobe_multi_opts"))
626d1320649SYonghong Song 		return;
627d1320649SYonghong Song 
628d1320649SYonghong Song 	detach_start_ns = get_time_ns();
629d1320649SYonghong Song 	bpf_link__destroy(link);
630d1320649SYonghong Song 	detach_end_ns = get_time_ns();
631d1320649SYonghong Song 
632d1320649SYonghong Song 	attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0;
633d1320649SYonghong Song 	detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0;
634d1320649SYonghong Song 
635d1320649SYonghong Song 	printf("%s: found %lu functions\n", __func__, opts->cnt);
636d1320649SYonghong Song 	printf("%s: attached in %7.3lfs\n", __func__, attach_delta);
637d1320649SYonghong Song 	printf("%s: detached in %7.3lfs\n", __func__, detach_delta);
638d1320649SYonghong Song }
639d1320649SYonghong Song 
test_kprobe_multi_bench_attach(bool kernel)640d1320649SYonghong Song static void test_kprobe_multi_bench_attach(bool kernel)
641d1320649SYonghong Song {
642d1320649SYonghong Song 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
643d1320649SYonghong Song 	struct kprobe_multi_empty *skel = NULL;
6445b6c7e5cSJiri Olsa 	char **syms = NULL;
6459edaafadSYonghong Song 	size_t cnt = 0;
6465b6c7e5cSJiri Olsa 
647edac4b5bSJiri Olsa 	if (!ASSERT_OK(get_syms(&syms, &cnt, kernel), "get_syms"))
6485b6c7e5cSJiri Olsa 		return;
6495b6c7e5cSJiri Olsa 
6505b6c7e5cSJiri Olsa 	skel = kprobe_multi_empty__open_and_load();
6515b6c7e5cSJiri Olsa 	if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
6525b6c7e5cSJiri Olsa 		goto cleanup;
6535b6c7e5cSJiri Olsa 
6545b6c7e5cSJiri Olsa 	opts.syms = (const char **) syms;
6555b6c7e5cSJiri Olsa 	opts.cnt = cnt;
6565b6c7e5cSJiri Olsa 
657d1320649SYonghong Song 	do_bench_test(skel, &opts);
6585b6c7e5cSJiri Olsa 
6595b6c7e5cSJiri Olsa cleanup:
6605b6c7e5cSJiri Olsa 	kprobe_multi_empty__destroy(skel);
6619edaafadSYonghong Song 	if (syms)
6625b6c7e5cSJiri Olsa 		free(syms);
6635b6c7e5cSJiri Olsa }
6645b6c7e5cSJiri Olsa 
test_kprobe_multi_bench_attach_addr(bool kernel)6656302bdebSYonghong Song static void test_kprobe_multi_bench_attach_addr(bool kernel)
6666302bdebSYonghong Song {
6676302bdebSYonghong Song 	LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
6686302bdebSYonghong Song 	struct kprobe_multi_empty *skel = NULL;
6696302bdebSYonghong Song 	unsigned long *addrs = NULL;
6706302bdebSYonghong Song 	size_t cnt = 0;
6716302bdebSYonghong Song 	int err;
6726302bdebSYonghong Song 
6736302bdebSYonghong Song 	err = get_addrs(&addrs, &cnt, kernel);
6746302bdebSYonghong Song 	if (err == -ENOENT) {
6756302bdebSYonghong Song 		test__skip();
6766302bdebSYonghong Song 		return;
6776302bdebSYonghong Song 	}
6786302bdebSYonghong Song 
6796302bdebSYonghong Song 	if (!ASSERT_OK(err, "get_addrs"))
6806302bdebSYonghong Song 		return;
6816302bdebSYonghong Song 
6826302bdebSYonghong Song 	skel = kprobe_multi_empty__open_and_load();
6836302bdebSYonghong Song 	if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
6846302bdebSYonghong Song 		goto cleanup;
6856302bdebSYonghong Song 
6866302bdebSYonghong Song 	opts.addrs = addrs;
6876302bdebSYonghong Song 	opts.cnt = cnt;
6886302bdebSYonghong Song 
6896302bdebSYonghong Song 	do_bench_test(skel, &opts);
6906302bdebSYonghong Song 
6916302bdebSYonghong Song cleanup:
6926302bdebSYonghong Song 	kprobe_multi_empty__destroy(skel);
6936302bdebSYonghong Song 	free(addrs);
6946302bdebSYonghong Song }
6956302bdebSYonghong Song 
test_attach_override(void)6968a19edd4SJiri Olsa static void test_attach_override(void)
6977182e564SJiri Olsa {
6987182e564SJiri Olsa 	struct kprobe_multi_override *skel = NULL;
6997182e564SJiri Olsa 	struct bpf_link *link = NULL;
7007182e564SJiri Olsa 
7017182e564SJiri Olsa 	skel = kprobe_multi_override__open_and_load();
7027182e564SJiri Olsa 	if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
7037182e564SJiri Olsa 		goto cleanup;
7047182e564SJiri Olsa 
7057182e564SJiri Olsa 	/* The test_override calls bpf_override_return so it should fail
7067182e564SJiri Olsa 	 * to attach to bpf_fentry_test1 function, which is not on error
7077182e564SJiri Olsa 	 * injection list.
7087182e564SJiri Olsa 	 */
7097182e564SJiri Olsa 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override,
7107182e564SJiri Olsa 						     "bpf_fentry_test1", NULL);
7117182e564SJiri Olsa 	if (!ASSERT_ERR_PTR(link, "override_attached_bpf_fentry_test1")) {
7127182e564SJiri Olsa 		bpf_link__destroy(link);
7137182e564SJiri Olsa 		goto cleanup;
7147182e564SJiri Olsa 	}
7157182e564SJiri Olsa 
7167182e564SJiri Olsa 	/* The should_fail_bio function is on error injection list,
7177182e564SJiri Olsa 	 * attach should succeed.
7187182e564SJiri Olsa 	 */
7197182e564SJiri Olsa 	link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override,
7207182e564SJiri Olsa 						     "should_fail_bio", NULL);
7217182e564SJiri Olsa 	if (!ASSERT_OK_PTR(link, "override_attached_should_fail_bio"))
7227182e564SJiri Olsa 		goto cleanup;
7237182e564SJiri Olsa 
7247182e564SJiri Olsa 	bpf_link__destroy(link);
7257182e564SJiri Olsa 
7267182e564SJiri Olsa cleanup:
7277182e564SJiri Olsa 	kprobe_multi_override__destroy(skel);
7287182e564SJiri Olsa }
7297182e564SJiri Olsa 
serial_test_kprobe_multi_bench_attach(void)730edac4b5bSJiri Olsa void serial_test_kprobe_multi_bench_attach(void)
731edac4b5bSJiri Olsa {
732edac4b5bSJiri Olsa 	if (test__start_subtest("kernel"))
733edac4b5bSJiri Olsa 		test_kprobe_multi_bench_attach(true);
734edac4b5bSJiri Olsa 	if (test__start_subtest("modules"))
735edac4b5bSJiri Olsa 		test_kprobe_multi_bench_attach(false);
7366302bdebSYonghong Song 	if (test__start_subtest("kernel"))
7376302bdebSYonghong Song 		test_kprobe_multi_bench_attach_addr(true);
7386302bdebSYonghong Song 	if (test__start_subtest("modules"))
7396302bdebSYonghong Song 		test_kprobe_multi_bench_attach_addr(false);
740edac4b5bSJiri Olsa }
741edac4b5bSJiri Olsa 
test_kprobe_multi_test(void)742f7a11eecSJiri Olsa void test_kprobe_multi_test(void)
743f7a11eecSJiri Olsa {
744f7a11eecSJiri Olsa 	if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
745f7a11eecSJiri Olsa 		return;
746f7a11eecSJiri Olsa 
747f7a11eecSJiri Olsa 	if (test__start_subtest("skel_api"))
748f7a11eecSJiri Olsa 		test_skel_api();
749f7a11eecSJiri Olsa 	if (test__start_subtest("link_api_addrs"))
750f7a11eecSJiri Olsa 		test_link_api_syms();
751f7a11eecSJiri Olsa 	if (test__start_subtest("link_api_syms"))
752f7a11eecSJiri Olsa 		test_link_api_addrs();
7539271a0c7SJiri Olsa 	if (test__start_subtest("attach_api_pattern"))
7549271a0c7SJiri Olsa 		test_attach_api_pattern();
7559271a0c7SJiri Olsa 	if (test__start_subtest("attach_api_addrs"))
7569271a0c7SJiri Olsa 		test_attach_api_addrs();
7579271a0c7SJiri Olsa 	if (test__start_subtest("attach_api_syms"))
7589271a0c7SJiri Olsa 		test_attach_api_syms();
7599271a0c7SJiri Olsa 	if (test__start_subtest("attach_api_fails"))
7609271a0c7SJiri Olsa 		test_attach_api_fails();
7617182e564SJiri Olsa 	if (test__start_subtest("attach_override"))
7627182e564SJiri Olsa 		test_attach_override();
7630983b169SJiri Olsa 	if (test__start_subtest("session"))
7640983b169SJiri Olsa 		test_session_skel_api();
765*a3a51133SJiri Olsa 	if (test__start_subtest("session_cookie"))
766*a3a51133SJiri Olsa 		test_session_cookie_skel_api();
767f7a11eecSJiri Olsa }
768