1*006004b7SJiri Olsa // SPDX-License-Identifier: GPL-2.0
2*006004b7SJiri Olsa #include <linux/bpf.h>
3*006004b7SJiri Olsa #include <bpf/bpf_helpers.h>
4*006004b7SJiri Olsa #include <bpf/bpf_tracing.h>
5*006004b7SJiri Olsa #include <errno.h>
6*006004b7SJiri Olsa 
7*006004b7SJiri Olsa char _license[] SEC("license") = "GPL";
8*006004b7SJiri Olsa 
9*006004b7SJiri Olsa __u64 test1_result = 0;
10*006004b7SJiri Olsa SEC("fentry/bpf_fentry_test1")
BPF_PROG(test1)11*006004b7SJiri Olsa int BPF_PROG(test1)
12*006004b7SJiri Olsa {
13*006004b7SJiri Olsa 	__u64 cnt = bpf_get_func_arg_cnt(ctx);
14*006004b7SJiri Olsa 	__u64 a = 0, z = 0, ret = 0;
15*006004b7SJiri Olsa 	__s64 err;
16*006004b7SJiri Olsa 
17*006004b7SJiri Olsa 	test1_result = cnt == 1;
18*006004b7SJiri Olsa 
19*006004b7SJiri Olsa 	/* valid arguments */
20*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 0, &a);
21*006004b7SJiri Olsa 
22*006004b7SJiri Olsa 	/* We need to cast access to traced function argument values with
23*006004b7SJiri Olsa 	 * proper type cast, because trampoline uses type specific instruction
24*006004b7SJiri Olsa 	 * to save it, like for 'int a' with 32-bit mov like:
25*006004b7SJiri Olsa 	 *
26*006004b7SJiri Olsa 	 *   mov %edi,-0x8(%rbp)
27*006004b7SJiri Olsa 	 *
28*006004b7SJiri Olsa 	 * so the upper 4 bytes are not zeroed.
29*006004b7SJiri Olsa 	 */
30*006004b7SJiri Olsa 	test1_result &= err == 0 && ((int) a == 1);
31*006004b7SJiri Olsa 
32*006004b7SJiri Olsa 	/* not valid argument */
33*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 1, &z);
34*006004b7SJiri Olsa 	test1_result &= err == -EINVAL;
35*006004b7SJiri Olsa 
36*006004b7SJiri Olsa 	/* return value fails in fentry */
37*006004b7SJiri Olsa 	err = bpf_get_func_ret(ctx, &ret);
38*006004b7SJiri Olsa 	test1_result &= err == -EOPNOTSUPP;
39*006004b7SJiri Olsa 	return 0;
40*006004b7SJiri Olsa }
41*006004b7SJiri Olsa 
42*006004b7SJiri Olsa __u64 test2_result = 0;
43*006004b7SJiri Olsa SEC("fexit/bpf_fentry_test2")
BPF_PROG(test2)44*006004b7SJiri Olsa int BPF_PROG(test2)
45*006004b7SJiri Olsa {
46*006004b7SJiri Olsa 	__u64 cnt = bpf_get_func_arg_cnt(ctx);
47*006004b7SJiri Olsa 	__u64 a = 0, b = 0, z = 0, ret = 0;
48*006004b7SJiri Olsa 	__s64 err;
49*006004b7SJiri Olsa 
50*006004b7SJiri Olsa 	test2_result = cnt == 2;
51*006004b7SJiri Olsa 
52*006004b7SJiri Olsa 	/* valid arguments */
53*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 0, &a);
54*006004b7SJiri Olsa 	test2_result &= err == 0 && (int) a == 2;
55*006004b7SJiri Olsa 
56*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 1, &b);
57*006004b7SJiri Olsa 	test2_result &= err == 0 && b == 3;
58*006004b7SJiri Olsa 
59*006004b7SJiri Olsa 	/* not valid argument */
60*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 2, &z);
61*006004b7SJiri Olsa 	test2_result &= err == -EINVAL;
62*006004b7SJiri Olsa 
63*006004b7SJiri Olsa 	/* return value */
64*006004b7SJiri Olsa 	err = bpf_get_func_ret(ctx, &ret);
65*006004b7SJiri Olsa 	test2_result &= err == 0 && ret == 5;
66*006004b7SJiri Olsa 	return 0;
67*006004b7SJiri Olsa }
68*006004b7SJiri Olsa 
69*006004b7SJiri Olsa __u64 test3_result = 0;
70*006004b7SJiri Olsa SEC("fmod_ret/bpf_modify_return_test")
BPF_PROG(fmod_ret_test,int _a,int * _b,int _ret)71*006004b7SJiri Olsa int BPF_PROG(fmod_ret_test, int _a, int *_b, int _ret)
72*006004b7SJiri Olsa {
73*006004b7SJiri Olsa 	__u64 cnt = bpf_get_func_arg_cnt(ctx);
74*006004b7SJiri Olsa 	__u64 a = 0, b = 0, z = 0, ret = 0;
75*006004b7SJiri Olsa 	__s64 err;
76*006004b7SJiri Olsa 
77*006004b7SJiri Olsa 	test3_result = cnt == 2;
78*006004b7SJiri Olsa 
79*006004b7SJiri Olsa 	/* valid arguments */
80*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 0, &a);
81*006004b7SJiri Olsa 	test3_result &= err == 0 && ((int) a == 1);
82*006004b7SJiri Olsa 
83*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 1, &b);
84*006004b7SJiri Olsa 	test3_result &= err == 0 && ((int *) b == _b);
85*006004b7SJiri Olsa 
86*006004b7SJiri Olsa 	/* not valid argument */
87*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 2, &z);
88*006004b7SJiri Olsa 	test3_result &= err == -EINVAL;
89*006004b7SJiri Olsa 
90*006004b7SJiri Olsa 	/* return value */
91*006004b7SJiri Olsa 	err = bpf_get_func_ret(ctx, &ret);
92*006004b7SJiri Olsa 	test3_result &= err == 0 && ret == 0;
93*006004b7SJiri Olsa 
94*006004b7SJiri Olsa 	/* change return value, it's checked in fexit_test program */
95*006004b7SJiri Olsa 	return 1234;
96*006004b7SJiri Olsa }
97*006004b7SJiri Olsa 
98*006004b7SJiri Olsa __u64 test4_result = 0;
99*006004b7SJiri Olsa SEC("fexit/bpf_modify_return_test")
BPF_PROG(fexit_test,int _a,int * _b,int _ret)100*006004b7SJiri Olsa int BPF_PROG(fexit_test, int _a, int *_b, int _ret)
101*006004b7SJiri Olsa {
102*006004b7SJiri Olsa 	__u64 cnt = bpf_get_func_arg_cnt(ctx);
103*006004b7SJiri Olsa 	__u64 a = 0, b = 0, z = 0, ret = 0;
104*006004b7SJiri Olsa 	__s64 err;
105*006004b7SJiri Olsa 
106*006004b7SJiri Olsa 	test4_result = cnt == 2;
107*006004b7SJiri Olsa 
108*006004b7SJiri Olsa 	/* valid arguments */
109*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 0, &a);
110*006004b7SJiri Olsa 	test4_result &= err == 0 && ((int) a == 1);
111*006004b7SJiri Olsa 
112*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 1, &b);
113*006004b7SJiri Olsa 	test4_result &= err == 0 && ((int *) b == _b);
114*006004b7SJiri Olsa 
115*006004b7SJiri Olsa 	/* not valid argument */
116*006004b7SJiri Olsa 	err = bpf_get_func_arg(ctx, 2, &z);
117*006004b7SJiri Olsa 	test4_result &= err == -EINVAL;
118*006004b7SJiri Olsa 
119*006004b7SJiri Olsa 	/* return value */
120*006004b7SJiri Olsa 	err = bpf_get_func_ret(ctx, &ret);
121*006004b7SJiri Olsa 	test4_result &= err == 0 && ret == 1234;
122*006004b7SJiri Olsa 	return 0;
123*006004b7SJiri Olsa }
124