1630301b0SAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2630301b0SAndrii Nakryiko /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3630301b0SAndrii Nakryiko #include <test_progs.h>
4630301b0SAndrii Nakryiko
5630301b0SAndrii Nakryiko #define _SDT_HAS_SEMAPHORES 1
6630301b0SAndrii Nakryiko #include "../sdt.h"
7630301b0SAndrii Nakryiko
8630301b0SAndrii Nakryiko #include "test_usdt.skel.h"
900a0fa2dSAndrii Nakryiko #include "test_urandom_usdt.skel.h"
10630301b0SAndrii Nakryiko
11630301b0SAndrii Nakryiko int lets_test_this(int);
12630301b0SAndrii Nakryiko
13630301b0SAndrii Nakryiko static volatile int idx = 2;
14630301b0SAndrii Nakryiko static volatile __u64 bla = 0xFEDCBA9876543210ULL;
15c46a1220SAndrii Nakryiko static volatile short nums[] = {-1, -2, -3, -4};
16630301b0SAndrii Nakryiko
17630301b0SAndrii Nakryiko static volatile struct {
18630301b0SAndrii Nakryiko int x;
19630301b0SAndrii Nakryiko signed char y;
20630301b0SAndrii Nakryiko } t1 = { 1, -127 };
21630301b0SAndrii Nakryiko
22630301b0SAndrii Nakryiko #define SEC(name) __attribute__((section(name), used))
23630301b0SAndrii Nakryiko
24630301b0SAndrii Nakryiko unsigned short test_usdt0_semaphore SEC(".probes");
25630301b0SAndrii Nakryiko unsigned short test_usdt3_semaphore SEC(".probes");
26630301b0SAndrii Nakryiko unsigned short test_usdt12_semaphore SEC(".probes");
27630301b0SAndrii Nakryiko
trigger_func(int x)28630301b0SAndrii Nakryiko static void __always_inline trigger_func(int x) {
29630301b0SAndrii Nakryiko long y = 42;
30630301b0SAndrii Nakryiko
31630301b0SAndrii Nakryiko if (test_usdt0_semaphore)
32630301b0SAndrii Nakryiko STAP_PROBE(test, usdt0);
33630301b0SAndrii Nakryiko if (test_usdt3_semaphore)
34630301b0SAndrii Nakryiko STAP_PROBE3(test, usdt3, x, y, &bla);
35630301b0SAndrii Nakryiko if (test_usdt12_semaphore) {
36630301b0SAndrii Nakryiko STAP_PROBE12(test, usdt12,
37630301b0SAndrii Nakryiko x, x + 1, y, x + y, 5,
38630301b0SAndrii Nakryiko y / 7, bla, &bla, -9, nums[x],
39630301b0SAndrii Nakryiko nums[idx], t1.y);
40630301b0SAndrii Nakryiko }
41630301b0SAndrii Nakryiko }
42630301b0SAndrii Nakryiko
subtest_basic_usdt(void)43630301b0SAndrii Nakryiko static void subtest_basic_usdt(void)
44630301b0SAndrii Nakryiko {
45630301b0SAndrii Nakryiko LIBBPF_OPTS(bpf_usdt_opts, opts);
46630301b0SAndrii Nakryiko struct test_usdt *skel;
47630301b0SAndrii Nakryiko struct test_usdt__bss *bss;
48630301b0SAndrii Nakryiko int err;
49630301b0SAndrii Nakryiko
50630301b0SAndrii Nakryiko skel = test_usdt__open_and_load();
51630301b0SAndrii Nakryiko if (!ASSERT_OK_PTR(skel, "skel_open"))
52630301b0SAndrii Nakryiko return;
53630301b0SAndrii Nakryiko
54630301b0SAndrii Nakryiko bss = skel->bss;
55630301b0SAndrii Nakryiko bss->my_pid = getpid();
56630301b0SAndrii Nakryiko
57630301b0SAndrii Nakryiko err = test_usdt__attach(skel);
58630301b0SAndrii Nakryiko if (!ASSERT_OK(err, "skel_attach"))
59630301b0SAndrii Nakryiko goto cleanup;
60630301b0SAndrii Nakryiko
61630301b0SAndrii Nakryiko /* usdt0 won't be auto-attached */
62630301b0SAndrii Nakryiko opts.usdt_cookie = 0xcafedeadbeeffeed;
63630301b0SAndrii Nakryiko skel->links.usdt0 = bpf_program__attach_usdt(skel->progs.usdt0,
64630301b0SAndrii Nakryiko 0 /*self*/, "/proc/self/exe",
65630301b0SAndrii Nakryiko "test", "usdt0", &opts);
66630301b0SAndrii Nakryiko if (!ASSERT_OK_PTR(skel->links.usdt0, "usdt0_link"))
67630301b0SAndrii Nakryiko goto cleanup;
68630301b0SAndrii Nakryiko
69630301b0SAndrii Nakryiko trigger_func(1);
70630301b0SAndrii Nakryiko
71630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt0_called, 1, "usdt0_called");
72630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_called, 1, "usdt3_called");
73630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_called, 1, "usdt12_called");
74630301b0SAndrii Nakryiko
75630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt0_cookie, 0xcafedeadbeeffeed, "usdt0_cookie");
76630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt0_arg_cnt, 0, "usdt0_arg_cnt");
77630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt0_arg_ret, -ENOENT, "usdt0_arg_ret");
78630301b0SAndrii Nakryiko
79630301b0SAndrii Nakryiko /* auto-attached usdt3 gets default zero cookie value */
80630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_cookie, 0, "usdt3_cookie");
81630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_cnt, 3, "usdt3_arg_cnt");
82630301b0SAndrii Nakryiko
83630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_rets[0], 0, "usdt3_arg1_ret");
84630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_rets[1], 0, "usdt3_arg2_ret");
85630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_rets[2], 0, "usdt3_arg3_ret");
86630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_args[0], 1, "usdt3_arg1");
87630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_args[1], 42, "usdt3_arg2");
88630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_args[2], (uintptr_t)&bla, "usdt3_arg3");
89630301b0SAndrii Nakryiko
90630301b0SAndrii Nakryiko /* auto-attached usdt12 gets default zero cookie value */
91630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_cookie, 0, "usdt12_cookie");
92630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_arg_cnt, 12, "usdt12_arg_cnt");
93630301b0SAndrii Nakryiko
94630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[0], 1, "usdt12_arg1");
95630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[1], 1 + 1, "usdt12_arg2");
96630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[2], 42, "usdt12_arg3");
97630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[3], 42 + 1, "usdt12_arg4");
98630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[4], 5, "usdt12_arg5");
99630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[5], 42 / 7, "usdt12_arg6");
100630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[6], bla, "usdt12_arg7");
101630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[7], (uintptr_t)&bla, "usdt12_arg8");
102630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[8], -9, "usdt12_arg9");
103630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[9], nums[1], "usdt12_arg10");
104630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[10], nums[idx], "usdt12_arg11");
105630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[11], t1.y, "usdt12_arg12");
106630301b0SAndrii Nakryiko
107630301b0SAndrii Nakryiko /* trigger_func() is marked __always_inline, so USDT invocations will be
108630301b0SAndrii Nakryiko * inlined in two different places, meaning that each USDT will have
109630301b0SAndrii Nakryiko * at least 2 different places to be attached to. This verifies that
110630301b0SAndrii Nakryiko * bpf_program__attach_usdt() handles this properly and attaches to
111630301b0SAndrii Nakryiko * all possible places of USDT invocation.
112630301b0SAndrii Nakryiko */
113630301b0SAndrii Nakryiko trigger_func(2);
114630301b0SAndrii Nakryiko
115630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt0_called, 2, "usdt0_called");
116630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_called, 2, "usdt3_called");
117630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_called, 2, "usdt12_called");
118630301b0SAndrii Nakryiko
119630301b0SAndrii Nakryiko /* only check values that depend on trigger_func()'s input value */
120630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_args[0], 2, "usdt3_arg1");
121630301b0SAndrii Nakryiko
122630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[0], 2, "usdt12_arg1");
123630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[1], 2 + 1, "usdt12_arg2");
124630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[3], 42 + 2, "usdt12_arg4");
125630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt12_args[9], nums[2], "usdt12_arg10");
126630301b0SAndrii Nakryiko
127630301b0SAndrii Nakryiko /* detach and re-attach usdt3 */
128630301b0SAndrii Nakryiko bpf_link__destroy(skel->links.usdt3);
129630301b0SAndrii Nakryiko
130630301b0SAndrii Nakryiko opts.usdt_cookie = 0xBADC00C51E;
131630301b0SAndrii Nakryiko skel->links.usdt3 = bpf_program__attach_usdt(skel->progs.usdt3, -1 /* any pid */,
132630301b0SAndrii Nakryiko "/proc/self/exe", "test", "usdt3", &opts);
133630301b0SAndrii Nakryiko if (!ASSERT_OK_PTR(skel->links.usdt3, "usdt3_reattach"))
134630301b0SAndrii Nakryiko goto cleanup;
135630301b0SAndrii Nakryiko
136630301b0SAndrii Nakryiko trigger_func(3);
137630301b0SAndrii Nakryiko
138630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_called, 3, "usdt3_called");
139630301b0SAndrii Nakryiko /* this time usdt3 has custom cookie */
140630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_cookie, 0xBADC00C51E, "usdt3_cookie");
141630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_cnt, 3, "usdt3_arg_cnt");
142630301b0SAndrii Nakryiko
143630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_rets[0], 0, "usdt3_arg1_ret");
144630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_rets[1], 0, "usdt3_arg2_ret");
145630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_arg_rets[2], 0, "usdt3_arg3_ret");
146630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_args[0], 3, "usdt3_arg1");
147630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_args[1], 42, "usdt3_arg2");
148630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt3_args[2], (uintptr_t)&bla, "usdt3_arg3");
149630301b0SAndrii Nakryiko
150630301b0SAndrii Nakryiko cleanup:
151630301b0SAndrii Nakryiko test_usdt__destroy(skel);
152630301b0SAndrii Nakryiko }
153630301b0SAndrii Nakryiko
154630301b0SAndrii Nakryiko unsigned short test_usdt_100_semaphore SEC(".probes");
155630301b0SAndrii Nakryiko unsigned short test_usdt_300_semaphore SEC(".probes");
156630301b0SAndrii Nakryiko unsigned short test_usdt_400_semaphore SEC(".probes");
157630301b0SAndrii Nakryiko
158630301b0SAndrii Nakryiko #define R10(F, X) F(X+0); F(X+1);F(X+2); F(X+3); F(X+4); \
159630301b0SAndrii Nakryiko F(X+5); F(X+6); F(X+7); F(X+8); F(X+9);
160630301b0SAndrii Nakryiko #define R100(F, X) R10(F,X+ 0);R10(F,X+10);R10(F,X+20);R10(F,X+30);R10(F,X+40); \
161630301b0SAndrii Nakryiko R10(F,X+50);R10(F,X+60);R10(F,X+70);R10(F,X+80);R10(F,X+90);
162630301b0SAndrii Nakryiko
163630301b0SAndrii Nakryiko /* carefully control that we get exactly 100 inlines by preventing inlining */
f100(int x)164630301b0SAndrii Nakryiko static void __always_inline f100(int x)
165630301b0SAndrii Nakryiko {
166630301b0SAndrii Nakryiko STAP_PROBE1(test, usdt_100, x);
167630301b0SAndrii Nakryiko }
168630301b0SAndrii Nakryiko
trigger_100_usdts(void)169630301b0SAndrii Nakryiko __weak void trigger_100_usdts(void)
170630301b0SAndrii Nakryiko {
171630301b0SAndrii Nakryiko R100(f100, 0);
172630301b0SAndrii Nakryiko }
173630301b0SAndrii Nakryiko
174630301b0SAndrii Nakryiko /* we shouldn't be able to attach to test:usdt2_300 USDT as we don't have as
175630301b0SAndrii Nakryiko * many slots for specs. It's important that each STAP_PROBE2() invocation
176630301b0SAndrii Nakryiko * (after untolling) gets different arg spec due to compiler inlining i as
177630301b0SAndrii Nakryiko * a constant
178630301b0SAndrii Nakryiko */
f300(int x)179630301b0SAndrii Nakryiko static void __always_inline f300(int x)
180630301b0SAndrii Nakryiko {
181630301b0SAndrii Nakryiko STAP_PROBE1(test, usdt_300, x);
182630301b0SAndrii Nakryiko }
183630301b0SAndrii Nakryiko
trigger_300_usdts(void)184630301b0SAndrii Nakryiko __weak void trigger_300_usdts(void)
185630301b0SAndrii Nakryiko {
186630301b0SAndrii Nakryiko R100(f300, 0);
187630301b0SAndrii Nakryiko R100(f300, 100);
188630301b0SAndrii Nakryiko R100(f300, 200);
189630301b0SAndrii Nakryiko }
190630301b0SAndrii Nakryiko
f400(int x)191630301b0SAndrii Nakryiko static void __always_inline f400(int x __attribute__((unused)))
192630301b0SAndrii Nakryiko {
1930d2d2648SAndrii Nakryiko STAP_PROBE1(test, usdt_400, 400);
194630301b0SAndrii Nakryiko }
195630301b0SAndrii Nakryiko
196630301b0SAndrii Nakryiko /* this time we have 400 different USDT call sites, but they have uniform
197630301b0SAndrii Nakryiko * argument location, so libbpf's spec string deduplication logic should keep
198630301b0SAndrii Nakryiko * spec count use very small and so we should be able to attach to all 400
199630301b0SAndrii Nakryiko * call sites
200630301b0SAndrii Nakryiko */
trigger_400_usdts(void)201630301b0SAndrii Nakryiko __weak void trigger_400_usdts(void)
202630301b0SAndrii Nakryiko {
203630301b0SAndrii Nakryiko R100(f400, 0);
204630301b0SAndrii Nakryiko R100(f400, 100);
205630301b0SAndrii Nakryiko R100(f400, 200);
206630301b0SAndrii Nakryiko R100(f400, 300);
207630301b0SAndrii Nakryiko }
208630301b0SAndrii Nakryiko
subtest_multispec_usdt(void)209630301b0SAndrii Nakryiko static void subtest_multispec_usdt(void)
210630301b0SAndrii Nakryiko {
211630301b0SAndrii Nakryiko LIBBPF_OPTS(bpf_usdt_opts, opts);
212630301b0SAndrii Nakryiko struct test_usdt *skel;
213630301b0SAndrii Nakryiko struct test_usdt__bss *bss;
214630301b0SAndrii Nakryiko int err, i;
215630301b0SAndrii Nakryiko
216630301b0SAndrii Nakryiko skel = test_usdt__open_and_load();
217630301b0SAndrii Nakryiko if (!ASSERT_OK_PTR(skel, "skel_open"))
218630301b0SAndrii Nakryiko return;
219630301b0SAndrii Nakryiko
220630301b0SAndrii Nakryiko bss = skel->bss;
221630301b0SAndrii Nakryiko bss->my_pid = getpid();
222630301b0SAndrii Nakryiko
223630301b0SAndrii Nakryiko err = test_usdt__attach(skel);
224630301b0SAndrii Nakryiko if (!ASSERT_OK(err, "skel_attach"))
225630301b0SAndrii Nakryiko goto cleanup;
226630301b0SAndrii Nakryiko
227630301b0SAndrii Nakryiko /* usdt_100 is auto-attached and there are 100 inlined call sites,
228630301b0SAndrii Nakryiko * let's validate that all of them are properly attached to and
229630301b0SAndrii Nakryiko * handled from BPF side
230630301b0SAndrii Nakryiko */
231630301b0SAndrii Nakryiko trigger_100_usdts();
232630301b0SAndrii Nakryiko
233630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_called, 100, "usdt_100_called");
234630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_sum, 99 * 100 / 2, "usdt_100_sum");
235630301b0SAndrii Nakryiko
236630301b0SAndrii Nakryiko /* Stress test free spec ID tracking. By default libbpf allows up to
237630301b0SAndrii Nakryiko * 256 specs to be used, so if we don't return free spec IDs back
238630301b0SAndrii Nakryiko * after few detachments and re-attachments we should run out of
239630301b0SAndrii Nakryiko * available spec IDs.
240630301b0SAndrii Nakryiko */
241630301b0SAndrii Nakryiko for (i = 0; i < 2; i++) {
242630301b0SAndrii Nakryiko bpf_link__destroy(skel->links.usdt_100);
243630301b0SAndrii Nakryiko
244630301b0SAndrii Nakryiko skel->links.usdt_100 = bpf_program__attach_usdt(skel->progs.usdt_100, -1,
245630301b0SAndrii Nakryiko "/proc/self/exe",
246630301b0SAndrii Nakryiko "test", "usdt_100", NULL);
247630301b0SAndrii Nakryiko if (!ASSERT_OK_PTR(skel->links.usdt_100, "usdt_100_reattach"))
248630301b0SAndrii Nakryiko goto cleanup;
249630301b0SAndrii Nakryiko
250630301b0SAndrii Nakryiko bss->usdt_100_sum = 0;
251630301b0SAndrii Nakryiko trigger_100_usdts();
252630301b0SAndrii Nakryiko
253630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_called, (i + 1) * 100 + 100, "usdt_100_called");
254630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_sum, 99 * 100 / 2, "usdt_100_sum");
255630301b0SAndrii Nakryiko }
256630301b0SAndrii Nakryiko
257630301b0SAndrii Nakryiko /* Now let's step it up and try to attach USDT that requires more than
258630301b0SAndrii Nakryiko * 256 attach points with different specs for each.
259630301b0SAndrii Nakryiko * Note that we need trigger_300_usdts() only to actually have 300
260630301b0SAndrii Nakryiko * USDT call sites, we are not going to actually trace them.
261630301b0SAndrii Nakryiko */
262630301b0SAndrii Nakryiko trigger_300_usdts();
263630301b0SAndrii Nakryiko
264630301b0SAndrii Nakryiko /* we'll reuse usdt_100 BPF program for usdt_300 test */
265630301b0SAndrii Nakryiko bpf_link__destroy(skel->links.usdt_100);
266630301b0SAndrii Nakryiko skel->links.usdt_100 = bpf_program__attach_usdt(skel->progs.usdt_100, -1, "/proc/self/exe",
267630301b0SAndrii Nakryiko "test", "usdt_300", NULL);
268630301b0SAndrii Nakryiko err = -errno;
269630301b0SAndrii Nakryiko if (!ASSERT_ERR_PTR(skel->links.usdt_100, "usdt_300_bad_attach"))
270630301b0SAndrii Nakryiko goto cleanup;
271630301b0SAndrii Nakryiko ASSERT_EQ(err, -E2BIG, "usdt_300_attach_err");
272630301b0SAndrii Nakryiko
273630301b0SAndrii Nakryiko /* let's check that there are no "dangling" BPF programs attached due
274630301b0SAndrii Nakryiko * to partial success of the above test:usdt_300 attachment
275630301b0SAndrii Nakryiko */
276630301b0SAndrii Nakryiko bss->usdt_100_called = 0;
277630301b0SAndrii Nakryiko bss->usdt_100_sum = 0;
278630301b0SAndrii Nakryiko
279630301b0SAndrii Nakryiko f300(777); /* this is 301st instance of usdt_300 */
280630301b0SAndrii Nakryiko
281630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_called, 0, "usdt_301_called");
282630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_sum, 0, "usdt_301_sum");
283630301b0SAndrii Nakryiko
284630301b0SAndrii Nakryiko /* This time we have USDT with 400 inlined invocations, but arg specs
285630301b0SAndrii Nakryiko * should be the same across all sites, so libbpf will only need to
286630301b0SAndrii Nakryiko * use one spec and thus we'll be able to attach 400 uprobes
287630301b0SAndrii Nakryiko * successfully.
288630301b0SAndrii Nakryiko *
289630301b0SAndrii Nakryiko * Again, we are reusing usdt_100 BPF program.
290630301b0SAndrii Nakryiko */
291630301b0SAndrii Nakryiko skel->links.usdt_100 = bpf_program__attach_usdt(skel->progs.usdt_100, -1,
292630301b0SAndrii Nakryiko "/proc/self/exe",
293630301b0SAndrii Nakryiko "test", "usdt_400", NULL);
294630301b0SAndrii Nakryiko if (!ASSERT_OK_PTR(skel->links.usdt_100, "usdt_400_attach"))
295630301b0SAndrii Nakryiko goto cleanup;
296630301b0SAndrii Nakryiko
297630301b0SAndrii Nakryiko trigger_400_usdts();
298630301b0SAndrii Nakryiko
299630301b0SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_called, 400, "usdt_400_called");
3000d2d2648SAndrii Nakryiko ASSERT_EQ(bss->usdt_100_sum, 400 * 400, "usdt_400_sum");
301630301b0SAndrii Nakryiko
302630301b0SAndrii Nakryiko cleanup:
303630301b0SAndrii Nakryiko test_usdt__destroy(skel);
304630301b0SAndrii Nakryiko }
305630301b0SAndrii Nakryiko
urand_spawn(int * pid)30600a0fa2dSAndrii Nakryiko static FILE *urand_spawn(int *pid)
30700a0fa2dSAndrii Nakryiko {
30800a0fa2dSAndrii Nakryiko FILE *f;
30900a0fa2dSAndrii Nakryiko
31000a0fa2dSAndrii Nakryiko /* urandom_read's stdout is wired into f */
31100a0fa2dSAndrii Nakryiko f = popen("./urandom_read 1 report-pid", "r");
31200a0fa2dSAndrii Nakryiko if (!f)
31300a0fa2dSAndrii Nakryiko return NULL;
31400a0fa2dSAndrii Nakryiko
31500a0fa2dSAndrii Nakryiko if (fscanf(f, "%d", pid) != 1) {
31600a0fa2dSAndrii Nakryiko pclose(f);
317*804acdd2SIlya Leoshkevich errno = EINVAL;
31800a0fa2dSAndrii Nakryiko return NULL;
31900a0fa2dSAndrii Nakryiko }
32000a0fa2dSAndrii Nakryiko
32100a0fa2dSAndrii Nakryiko return f;
32200a0fa2dSAndrii Nakryiko }
32300a0fa2dSAndrii Nakryiko
urand_trigger(FILE ** urand_pipe)32400a0fa2dSAndrii Nakryiko static int urand_trigger(FILE **urand_pipe)
32500a0fa2dSAndrii Nakryiko {
32600a0fa2dSAndrii Nakryiko int exit_code;
32700a0fa2dSAndrii Nakryiko
32800a0fa2dSAndrii Nakryiko /* pclose() waits for child process to exit and returns their exit code */
32900a0fa2dSAndrii Nakryiko exit_code = pclose(*urand_pipe);
33000a0fa2dSAndrii Nakryiko *urand_pipe = NULL;
33100a0fa2dSAndrii Nakryiko
33200a0fa2dSAndrii Nakryiko return exit_code;
33300a0fa2dSAndrii Nakryiko }
33400a0fa2dSAndrii Nakryiko
subtest_urandom_usdt(bool auto_attach)33500a0fa2dSAndrii Nakryiko static void subtest_urandom_usdt(bool auto_attach)
33600a0fa2dSAndrii Nakryiko {
33700a0fa2dSAndrii Nakryiko struct test_urandom_usdt *skel;
33800a0fa2dSAndrii Nakryiko struct test_urandom_usdt__bss *bss;
33900a0fa2dSAndrii Nakryiko struct bpf_link *l;
34000a0fa2dSAndrii Nakryiko FILE *urand_pipe = NULL;
34100a0fa2dSAndrii Nakryiko int err, urand_pid = 0;
34200a0fa2dSAndrii Nakryiko
34300a0fa2dSAndrii Nakryiko skel = test_urandom_usdt__open_and_load();
34400a0fa2dSAndrii Nakryiko if (!ASSERT_OK_PTR(skel, "skel_open"))
34500a0fa2dSAndrii Nakryiko return;
34600a0fa2dSAndrii Nakryiko
34700a0fa2dSAndrii Nakryiko urand_pipe = urand_spawn(&urand_pid);
34800a0fa2dSAndrii Nakryiko if (!ASSERT_OK_PTR(urand_pipe, "urand_spawn"))
34900a0fa2dSAndrii Nakryiko goto cleanup;
35000a0fa2dSAndrii Nakryiko
35100a0fa2dSAndrii Nakryiko bss = skel->bss;
35200a0fa2dSAndrii Nakryiko bss->urand_pid = urand_pid;
35300a0fa2dSAndrii Nakryiko
35400a0fa2dSAndrii Nakryiko if (auto_attach) {
35500a0fa2dSAndrii Nakryiko err = test_urandom_usdt__attach(skel);
35600a0fa2dSAndrii Nakryiko if (!ASSERT_OK(err, "skel_auto_attach"))
35700a0fa2dSAndrii Nakryiko goto cleanup;
35800a0fa2dSAndrii Nakryiko } else {
35900a0fa2dSAndrii Nakryiko l = bpf_program__attach_usdt(skel->progs.urand_read_without_sema,
36000a0fa2dSAndrii Nakryiko urand_pid, "./urandom_read",
36100a0fa2dSAndrii Nakryiko "urand", "read_without_sema", NULL);
36200a0fa2dSAndrii Nakryiko if (!ASSERT_OK_PTR(l, "urand_without_sema_attach"))
36300a0fa2dSAndrii Nakryiko goto cleanup;
36400a0fa2dSAndrii Nakryiko skel->links.urand_read_without_sema = l;
36500a0fa2dSAndrii Nakryiko
36600a0fa2dSAndrii Nakryiko l = bpf_program__attach_usdt(skel->progs.urand_read_with_sema,
36700a0fa2dSAndrii Nakryiko urand_pid, "./urandom_read",
36800a0fa2dSAndrii Nakryiko "urand", "read_with_sema", NULL);
36900a0fa2dSAndrii Nakryiko if (!ASSERT_OK_PTR(l, "urand_with_sema_attach"))
37000a0fa2dSAndrii Nakryiko goto cleanup;
37100a0fa2dSAndrii Nakryiko skel->links.urand_read_with_sema = l;
37200a0fa2dSAndrii Nakryiko
37300a0fa2dSAndrii Nakryiko l = bpf_program__attach_usdt(skel->progs.urandlib_read_without_sema,
37400a0fa2dSAndrii Nakryiko urand_pid, "./liburandom_read.so",
37500a0fa2dSAndrii Nakryiko "urandlib", "read_without_sema", NULL);
37600a0fa2dSAndrii Nakryiko if (!ASSERT_OK_PTR(l, "urandlib_without_sema_attach"))
37700a0fa2dSAndrii Nakryiko goto cleanup;
37800a0fa2dSAndrii Nakryiko skel->links.urandlib_read_without_sema = l;
37900a0fa2dSAndrii Nakryiko
38000a0fa2dSAndrii Nakryiko l = bpf_program__attach_usdt(skel->progs.urandlib_read_with_sema,
38100a0fa2dSAndrii Nakryiko urand_pid, "./liburandom_read.so",
38200a0fa2dSAndrii Nakryiko "urandlib", "read_with_sema", NULL);
38300a0fa2dSAndrii Nakryiko if (!ASSERT_OK_PTR(l, "urandlib_with_sema_attach"))
38400a0fa2dSAndrii Nakryiko goto cleanup;
38500a0fa2dSAndrii Nakryiko skel->links.urandlib_read_with_sema = l;
38600a0fa2dSAndrii Nakryiko
38700a0fa2dSAndrii Nakryiko }
38800a0fa2dSAndrii Nakryiko
38900a0fa2dSAndrii Nakryiko /* trigger urandom_read USDTs */
39000a0fa2dSAndrii Nakryiko ASSERT_OK(urand_trigger(&urand_pipe), "urand_exit_code");
39100a0fa2dSAndrii Nakryiko
39200a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urand_read_without_sema_call_cnt, 1, "urand_wo_sema_cnt");
39300a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urand_read_without_sema_buf_sz_sum, 256, "urand_wo_sema_sum");
39400a0fa2dSAndrii Nakryiko
39500a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urand_read_with_sema_call_cnt, 1, "urand_w_sema_cnt");
39600a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urand_read_with_sema_buf_sz_sum, 256, "urand_w_sema_sum");
39700a0fa2dSAndrii Nakryiko
39800a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urandlib_read_without_sema_call_cnt, 1, "urandlib_wo_sema_cnt");
39900a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urandlib_read_without_sema_buf_sz_sum, 256, "urandlib_wo_sema_sum");
40000a0fa2dSAndrii Nakryiko
40100a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urandlib_read_with_sema_call_cnt, 1, "urandlib_w_sema_cnt");
40200a0fa2dSAndrii Nakryiko ASSERT_EQ(bss->urandlib_read_with_sema_buf_sz_sum, 256, "urandlib_w_sema_sum");
40300a0fa2dSAndrii Nakryiko
40400a0fa2dSAndrii Nakryiko cleanup:
40500a0fa2dSAndrii Nakryiko if (urand_pipe)
40600a0fa2dSAndrii Nakryiko pclose(urand_pipe);
40700a0fa2dSAndrii Nakryiko test_urandom_usdt__destroy(skel);
40800a0fa2dSAndrii Nakryiko }
40900a0fa2dSAndrii Nakryiko
test_usdt(void)410630301b0SAndrii Nakryiko void test_usdt(void)
411630301b0SAndrii Nakryiko {
412630301b0SAndrii Nakryiko if (test__start_subtest("basic"))
413630301b0SAndrii Nakryiko subtest_basic_usdt();
414630301b0SAndrii Nakryiko if (test__start_subtest("multispec"))
415630301b0SAndrii Nakryiko subtest_multispec_usdt();
41600a0fa2dSAndrii Nakryiko if (test__start_subtest("urand_auto_attach"))
41700a0fa2dSAndrii Nakryiko subtest_urandom_usdt(true /* auto_attach */);
41800a0fa2dSAndrii Nakryiko if (test__start_subtest("urand_pid_attach"))
41900a0fa2dSAndrii Nakryiko subtest_urandom_usdt(false /* auto_attach */);
420630301b0SAndrii Nakryiko }
421