1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2021 Facebook */ |
3 | |
4 | #include "vmlinux.h" |
5 | #include <bpf/bpf_helpers.h> |
6 | #include <bpf/bpf_tracing.h> |
7 | #include <bpf/bpf_core_read.h> |
8 | #include "bpf_misc.h" |
9 | |
10 | /* weak and shared between two files */ |
11 | const volatile __u32 my_tid __weak; |
12 | long syscall_id __weak; |
13 | |
14 | int output_val1; |
15 | int output_ctx1; |
16 | int output_weak1; |
17 | |
18 | /* same "subprog" name in all files, but it's ok because they all are static */ |
19 | static __noinline int subprog(int x) |
20 | { |
21 | /* but different formula */ |
22 | return x * 1; |
23 | } |
24 | |
25 | /* Global functions can't be void */ |
26 | int set_output_val1(int x) |
27 | { |
28 | output_val1 = x + subprog(x); |
29 | return x; |
30 | } |
31 | |
32 | /* This function can't be verified as global, as it assumes raw_tp/sys_enter |
33 | * context and accesses syscall id (second argument). So we mark it as |
34 | * __hidden, so that libbpf will mark it as static in the final object file, |
35 | * right before verifying it in the kernel. |
36 | * |
37 | * But we don't mark it as __hidden here, rather at extern site. __hidden is |
38 | * "contaminating" visibility, so it will get propagated from either extern or |
39 | * actual definition (including from the losing __weak definition). |
40 | */ |
41 | void set_output_ctx1(__u64 *ctx) |
42 | { |
43 | output_ctx1 = ctx[1]; /* long id, same as in BPF_PROG below */ |
44 | } |
45 | |
46 | /* this weak instance should win because it's the first one */ |
47 | __weak int set_output_weak(int x) |
48 | { |
49 | static volatile int whatever; |
50 | |
51 | /* make sure we use CO-RE relocations in a weak function, this used to |
52 | * cause problems for BPF static linker |
53 | */ |
54 | whatever = bpf_core_type_size(struct task_struct); |
55 | __sink(whatever); |
56 | |
57 | output_weak1 = x; |
58 | return x; |
59 | } |
60 | |
61 | extern int set_output_val2(int x); |
62 | |
63 | /* here we'll force set_output_ctx2() to be __hidden in the final obj file */ |
64 | __hidden extern void set_output_ctx2(__u64 *ctx); |
65 | |
66 | SEC("?raw_tp/sys_enter" ) |
67 | int BPF_PROG(handler1, struct pt_regs *regs, long id) |
68 | { |
69 | static volatile int whatever; |
70 | |
71 | if (my_tid != (u32)bpf_get_current_pid_tgid() || id != syscall_id) |
72 | return 0; |
73 | |
74 | /* make sure we have CO-RE relocations in main program */ |
75 | whatever = bpf_core_type_size(struct task_struct); |
76 | __sink(whatever); |
77 | |
78 | set_output_val2(1000); |
79 | set_output_ctx2(ctx); /* ctx definition is hidden in BPF_PROG macro */ |
80 | |
81 | /* keep input value the same across both files to avoid dependency on |
82 | * handler call order; differentiate by output_weak1 vs output_weak2. |
83 | */ |
84 | set_output_weak(42); |
85 | |
86 | return 0; |
87 | } |
88 | |
89 | char LICENSE[] SEC("license" ) = "GPL" ; |
90 | |