1#include "vmlinux.h"
2#include <bpf/bpf_helpers.h>
3#include <bpf/bpf_core_read.h>
4
5const char LICENSE[] SEC("license") = "GPL";
6
7__noinline int sub1(int x)
8{
9	return x + 1;
10}
11
12static __noinline int sub5(int v);
13
14__noinline int sub2(int y)
15{
16	return sub5(y + 2);
17}
18
19static __noinline int sub3(int z)
20{
21	return z + 3 + sub1(4);
22}
23
24static __noinline int sub4(int w)
25{
26	return w + sub3(5) + sub1(6);
27}
28
29/* sub5() is an identitify function, just to test weirder functions layout and
30 * call patterns
31 */
32static __noinline int sub5(int v)
33{
34	return sub1(v) - 1; /* compensates sub1()'s + 1 */
35}
36
37/* unfortunately verifier rejects `struct task_struct *t` as an unkown pointer
38 * type, so we need to accept pointer as integer and then cast it inside the
39 * function
40 */
41__noinline int get_task_tgid(uintptr_t t)
42{
43	/* this ensures that CO-RE relocs work in multi-subprogs .text */
44	return BPF_CORE_READ((struct task_struct *)(void *)t, tgid);
45}
46
47int res1 = 0;
48int res2 = 0;
49int res3 = 0;
50int res4 = 0;
51
52SEC("raw_tp/sys_enter")
53int prog1(void *ctx)
54{
55	/* perform some CO-RE relocations to ensure they work with multi-prog
56	 * sections correctly
57	 */
58	struct task_struct *t = (void *)bpf_get_current_task();
59
60	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
61		return 1;
62
63	res1 = sub1(1) + sub3(2); /* (1 + 1) + (2 + 3 + (4 + 1)) = 12 */
64	return 0;
65}
66
67SEC("raw_tp/sys_exit")
68int prog2(void *ctx)
69{
70	struct task_struct *t = (void *)bpf_get_current_task();
71
72	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
73		return 1;
74
75	res2 = sub2(3) + sub3(4); /* (3 + 2) + (4 + 3 + (4 + 1)) = 17 */
76	return 0;
77}
78
79/* prog3 has the same section name as prog1 */
80SEC("raw_tp/sys_enter")
81int prog3(void *ctx)
82{
83	struct task_struct *t = (void *)bpf_get_current_task();
84
85	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
86		return 1;
87
88	res3 = sub3(5) + 6; /* (5 + 3 + (4 + 1)) + 6 = 19 */
89	return 0;
90}
91
92/* prog4 has the same section name as prog2 */
93SEC("raw_tp/sys_exit")
94int prog4(void *ctx)
95{
96	struct task_struct *t = (void *)bpf_get_current_task();
97
98	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
99		return 1;
100
101	res4 = sub4(7) + sub1(8); /* (7 + (5 + 3 + (4 + 1)) + (6 + 1)) + (8 + 1) = 36 */
102	return 0;
103}
104