Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add global variables linking selftest

Add selftest validating various aspects of statically linking global
variables:
- correct resolution of extern variables across .bss, .data, and .rodata
sections;
- correct handling of weak definitions;
- correct de-duplication of repeating special externs (.kconfig, .ksyms).

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20210423181348.1801389-17-andrii@kernel.org

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
14f1aae1 f2644fb4

+154 -1
+2 -1
tools/testing/selftests/bpf/Makefile
··· 309 309 310 310 SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c 311 311 312 - LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h 312 + LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h linked_vars.skel.h 313 313 314 314 test_static_linked.skel.h-deps := test_static_linked1.o test_static_linked2.o 315 315 linked_funcs.skel.h-deps := linked_funcs1.o linked_funcs2.o 316 + linked_vars.skel.h-deps := linked_vars1.o linked_vars2.o 316 317 317 318 LINKED_BPF_SRCS := $(patsubst %.o,%.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps))) 318 319
+43
tools/testing/selftests/bpf/prog_tests/linked_vars.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2021 Facebook */ 3 + 4 + #include <test_progs.h> 5 + #include <sys/syscall.h> 6 + #include "linked_vars.skel.h" 7 + 8 + void test_linked_vars(void) 9 + { 10 + int err; 11 + struct linked_vars *skel; 12 + 13 + skel = linked_vars__open(); 14 + if (!ASSERT_OK_PTR(skel, "skel_open")) 15 + return; 16 + 17 + skel->bss->input_bss1 = 1000; 18 + skel->bss->input_bss2 = 2000; 19 + skel->bss->input_bss_weak = 3000; 20 + 21 + err = linked_vars__load(skel); 22 + if (!ASSERT_OK(err, "skel_load")) 23 + goto cleanup; 24 + 25 + err = linked_vars__attach(skel); 26 + if (!ASSERT_OK(err, "skel_attach")) 27 + goto cleanup; 28 + 29 + /* trigger */ 30 + syscall(SYS_getpgid); 31 + 32 + ASSERT_EQ(skel->bss->output_bss1, 1000 + 2000 + 3000, "output_bss1"); 33 + ASSERT_EQ(skel->bss->output_bss2, 1000 + 2000 + 3000, "output_bss2"); 34 + /* 10 comes from "winner" input_data_weak in first obj file */ 35 + ASSERT_EQ(skel->bss->output_data1, 1 + 2 + 10, "output_bss1"); 36 + ASSERT_EQ(skel->bss->output_data2, 1 + 2 + 10, "output_bss2"); 37 + /* 100 comes from "winner" input_rodata_weak in first obj file */ 38 + ASSERT_EQ(skel->bss->output_rodata1, 11 + 22 + 100, "output_weak1"); 39 + ASSERT_EQ(skel->bss->output_rodata2, 11 + 22 + 100, "output_weak2"); 40 + 41 + cleanup: 42 + linked_vars__destroy(skel); 43 + }
+54
tools/testing/selftests/bpf/progs/linked_vars1.c
··· 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 + 8 + extern int LINUX_KERNEL_VERSION __kconfig; 9 + /* this weak extern will be strict due to the other file's strong extern */ 10 + extern bool CONFIG_BPF_SYSCALL __kconfig __weak; 11 + extern const void bpf_link_fops __ksym __weak; 12 + 13 + int input_bss1; 14 + int input_data1 = 1; 15 + const volatile int input_rodata1 = 11; 16 + 17 + int input_bss_weak __weak; 18 + /* these two definitions should win */ 19 + int input_data_weak __weak = 10; 20 + const volatile int input_rodata_weak __weak = 100; 21 + 22 + extern int input_bss2; 23 + extern int input_data2; 24 + extern const int input_rodata2; 25 + 26 + int output_bss1; 27 + int output_data1; 28 + int output_rodata1; 29 + 30 + long output_sink1; 31 + 32 + static __noinline int get_bss_res(void) 33 + { 34 + /* just make sure all the relocations work against .text as well */ 35 + return input_bss1 + input_bss2 + input_bss_weak; 36 + } 37 + 38 + SEC("raw_tp/sys_enter") 39 + int BPF_PROG(handler1) 40 + { 41 + output_bss1 = get_bss_res(); 42 + output_data1 = input_data1 + input_data2 + input_data_weak; 43 + output_rodata1 = input_rodata1 + input_rodata2 + input_rodata_weak; 44 + 45 + /* make sure we actually use above special externs, otherwise compiler 46 + * will optimize them out 47 + */ 48 + output_sink1 = LINUX_KERNEL_VERSION 49 + + CONFIG_BPF_SYSCALL 50 + + (long)&bpf_link_fops; 51 + return 0; 52 + } 53 + 54 + char LICENSE[] SEC("license") = "GPL";
+55
tools/testing/selftests/bpf/progs/linked_vars2.c
··· 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 + 8 + extern int LINUX_KERNEL_VERSION __kconfig; 9 + /* when an extern is defined as both strong and weak, resulting symbol will be strong */ 10 + extern bool CONFIG_BPF_SYSCALL __kconfig; 11 + extern const void __start_BTF __ksym; 12 + 13 + int input_bss2; 14 + int input_data2 = 2; 15 + const volatile int input_rodata2 = 22; 16 + 17 + int input_bss_weak __weak; 18 + /* these two weak variables should lose */ 19 + int input_data_weak __weak = 20; 20 + const volatile int input_rodata_weak __weak = 200; 21 + 22 + extern int input_bss1; 23 + extern int input_data1; 24 + extern const int input_rodata1; 25 + 26 + int output_bss2; 27 + int output_data2; 28 + int output_rodata2; 29 + 30 + int output_sink2; 31 + 32 + static __noinline int get_data_res(void) 33 + { 34 + /* just make sure all the relocations work against .text as well */ 35 + return input_data1 + input_data2 + input_data_weak; 36 + } 37 + 38 + SEC("raw_tp/sys_enter") 39 + int BPF_PROG(handler2) 40 + { 41 + output_bss2 = input_bss1 + input_bss2 + input_bss_weak; 42 + output_data2 = get_data_res(); 43 + output_rodata2 = input_rodata1 + input_rodata2 + input_rodata_weak; 44 + 45 + /* make sure we actually use above special externs, otherwise compiler 46 + * will optimize them out 47 + */ 48 + output_sink2 = LINUX_KERNEL_VERSION 49 + + CONFIG_BPF_SYSCALL 50 + + (long)&__start_BTF; 51 + 52 + return 0; 53 + } 54 + 55 + char LICENSE[] SEC("license") = "GPL";