1a08c02f8SAndrii Nakryiko #include "vmlinux.h"
2a08c02f8SAndrii Nakryiko #include <bpf/bpf_helpers.h>
3a08c02f8SAndrii Nakryiko #include <bpf/bpf_core_read.h>
4a08c02f8SAndrii Nakryiko 
5a08c02f8SAndrii Nakryiko const char LICENSE[] SEC("license") = "GPL";
6a08c02f8SAndrii Nakryiko 
7b1268826SAlexei Starovoitov struct {
8b1268826SAlexei Starovoitov 	__uint(type, BPF_MAP_TYPE_ARRAY);
9b1268826SAlexei Starovoitov 	__uint(max_entries, 1);
10b1268826SAlexei Starovoitov 	__type(key, __u32);
11b1268826SAlexei Starovoitov 	__type(value, __u64);
12b1268826SAlexei Starovoitov } array SEC(".maps");
13b1268826SAlexei Starovoitov 
sub1(int x)14a08c02f8SAndrii Nakryiko __noinline int sub1(int x)
15a08c02f8SAndrii Nakryiko {
16b1268826SAlexei Starovoitov 	int key = 0;
17b1268826SAlexei Starovoitov 
18b1268826SAlexei Starovoitov 	bpf_map_lookup_elem(&array, &key);
19a08c02f8SAndrii Nakryiko 	return x + 1;
20a08c02f8SAndrii Nakryiko }
21a08c02f8SAndrii Nakryiko 
22a08c02f8SAndrii Nakryiko static __noinline int sub5(int v);
23a08c02f8SAndrii Nakryiko 
sub2(int y)24a08c02f8SAndrii Nakryiko __noinline int sub2(int y)
25a08c02f8SAndrii Nakryiko {
26a08c02f8SAndrii Nakryiko 	return sub5(y + 2);
27a08c02f8SAndrii Nakryiko }
28a08c02f8SAndrii Nakryiko 
sub3(int z)29a08c02f8SAndrii Nakryiko static __noinline int sub3(int z)
30a08c02f8SAndrii Nakryiko {
31a08c02f8SAndrii Nakryiko 	return z + 3 + sub1(4);
32a08c02f8SAndrii Nakryiko }
33a08c02f8SAndrii Nakryiko 
sub4(int w)34a08c02f8SAndrii Nakryiko static __noinline int sub4(int w)
35a08c02f8SAndrii Nakryiko {
36b1268826SAlexei Starovoitov 	int key = 0;
37b1268826SAlexei Starovoitov 
38b1268826SAlexei Starovoitov 	bpf_map_lookup_elem(&array, &key);
39a08c02f8SAndrii Nakryiko 	return w + sub3(5) + sub1(6);
40a08c02f8SAndrii Nakryiko }
41a08c02f8SAndrii Nakryiko 
42a08c02f8SAndrii Nakryiko /* sub5() is an identitify function, just to test weirder functions layout and
43a08c02f8SAndrii Nakryiko  * call patterns
44a08c02f8SAndrii Nakryiko  */
sub5(int v)45a08c02f8SAndrii Nakryiko static __noinline int sub5(int v)
46a08c02f8SAndrii Nakryiko {
47a08c02f8SAndrii Nakryiko 	return sub1(v) - 1; /* compensates sub1()'s + 1 */
48a08c02f8SAndrii Nakryiko }
49a08c02f8SAndrii Nakryiko 
50*df71a42cSTaichi Nishimura /* unfortunately verifier rejects `struct task_struct *t` as an unknown pointer
51a08c02f8SAndrii Nakryiko  * type, so we need to accept pointer as integer and then cast it inside the
52a08c02f8SAndrii Nakryiko  * function
53a08c02f8SAndrii Nakryiko  */
get_task_tgid(uintptr_t t)54a08c02f8SAndrii Nakryiko __noinline int get_task_tgid(uintptr_t t)
55a08c02f8SAndrii Nakryiko {
56a08c02f8SAndrii Nakryiko 	/* this ensures that CO-RE relocs work in multi-subprogs .text */
57a08c02f8SAndrii Nakryiko 	return BPF_CORE_READ((struct task_struct *)(void *)t, tgid);
58a08c02f8SAndrii Nakryiko }
59a08c02f8SAndrii Nakryiko 
60a08c02f8SAndrii Nakryiko int res1 = 0;
61a08c02f8SAndrii Nakryiko int res2 = 0;
62a08c02f8SAndrii Nakryiko int res3 = 0;
63a08c02f8SAndrii Nakryiko int res4 = 0;
64a08c02f8SAndrii Nakryiko 
65a08c02f8SAndrii Nakryiko SEC("raw_tp/sys_enter")
prog1(void * ctx)66a08c02f8SAndrii Nakryiko int prog1(void *ctx)
67a08c02f8SAndrii Nakryiko {
68a08c02f8SAndrii Nakryiko 	/* perform some CO-RE relocations to ensure they work with multi-prog
69a08c02f8SAndrii Nakryiko 	 * sections correctly
70a08c02f8SAndrii Nakryiko 	 */
71a08c02f8SAndrii Nakryiko 	struct task_struct *t = (void *)bpf_get_current_task();
72a08c02f8SAndrii Nakryiko 
73a08c02f8SAndrii Nakryiko 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
74a08c02f8SAndrii Nakryiko 		return 1;
75a08c02f8SAndrii Nakryiko 
76a08c02f8SAndrii Nakryiko 	res1 = sub1(1) + sub3(2); /* (1 + 1) + (2 + 3 + (4 + 1)) = 12 */
77a08c02f8SAndrii Nakryiko 	return 0;
78a08c02f8SAndrii Nakryiko }
79a08c02f8SAndrii Nakryiko 
80a08c02f8SAndrii Nakryiko SEC("raw_tp/sys_exit")
prog2(void * ctx)81a08c02f8SAndrii Nakryiko int prog2(void *ctx)
82a08c02f8SAndrii Nakryiko {
83a08c02f8SAndrii Nakryiko 	struct task_struct *t = (void *)bpf_get_current_task();
84a08c02f8SAndrii Nakryiko 
85a08c02f8SAndrii Nakryiko 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
86a08c02f8SAndrii Nakryiko 		return 1;
87a08c02f8SAndrii Nakryiko 
88a08c02f8SAndrii Nakryiko 	res2 = sub2(3) + sub3(4); /* (3 + 2) + (4 + 3 + (4 + 1)) = 17 */
89a08c02f8SAndrii Nakryiko 	return 0;
90a08c02f8SAndrii Nakryiko }
91a08c02f8SAndrii Nakryiko 
empty_callback(__u32 index,void * data)92365d5199SAlexei Starovoitov static int empty_callback(__u32 index, void *data)
93365d5199SAlexei Starovoitov {
94365d5199SAlexei Starovoitov 	return 0;
95365d5199SAlexei Starovoitov }
96365d5199SAlexei Starovoitov 
97a08c02f8SAndrii Nakryiko /* prog3 has the same section name as prog1 */
98a08c02f8SAndrii Nakryiko SEC("raw_tp/sys_enter")
prog3(void * ctx)99a08c02f8SAndrii Nakryiko int prog3(void *ctx)
100a08c02f8SAndrii Nakryiko {
101a08c02f8SAndrii Nakryiko 	struct task_struct *t = (void *)bpf_get_current_task();
102a08c02f8SAndrii Nakryiko 
103a08c02f8SAndrii Nakryiko 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
104a08c02f8SAndrii Nakryiko 		return 1;
105a08c02f8SAndrii Nakryiko 
106365d5199SAlexei Starovoitov 	/* test that ld_imm64 with BPF_PSEUDO_FUNC doesn't get blinded */
107365d5199SAlexei Starovoitov 	bpf_loop(1, empty_callback, NULL, 0);
108365d5199SAlexei Starovoitov 
109a08c02f8SAndrii Nakryiko 	res3 = sub3(5) + 6; /* (5 + 3 + (4 + 1)) + 6 = 19 */
110a08c02f8SAndrii Nakryiko 	return 0;
111a08c02f8SAndrii Nakryiko }
112a08c02f8SAndrii Nakryiko 
113a08c02f8SAndrii Nakryiko /* prog4 has the same section name as prog2 */
114a08c02f8SAndrii Nakryiko SEC("raw_tp/sys_exit")
prog4(void * ctx)115a08c02f8SAndrii Nakryiko int prog4(void *ctx)
116a08c02f8SAndrii Nakryiko {
117a08c02f8SAndrii Nakryiko 	struct task_struct *t = (void *)bpf_get_current_task();
118a08c02f8SAndrii Nakryiko 
119a08c02f8SAndrii Nakryiko 	if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
120a08c02f8SAndrii Nakryiko 		return 1;
121a08c02f8SAndrii Nakryiko 
122a08c02f8SAndrii Nakryiko 	res4 = sub4(7) + sub1(8); /* (7 + (5 + 3 + (4 + 1)) + (6 + 1)) + (8 + 1) = 36 */
123a08c02f8SAndrii Nakryiko 	return 0;
124a08c02f8SAndrii Nakryiko }
125