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

selftests/bpf: Add __ksym extern selftest

Validate libbpf is able to handle weak and strong kernel symbol externs in BPF
code correctly.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Hao Luo <haoluo@google.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-4-andriin@fb.com

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
b7ddfab2 1c0c7074

+103
+71
tools/testing/selftests/bpf/prog_tests/ksyms.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2019 Facebook */ 3 + 4 + #include <test_progs.h> 5 + #include "test_ksyms.skel.h" 6 + #include <sys/stat.h> 7 + 8 + static int duration; 9 + 10 + static __u64 kallsyms_find(const char *sym) 11 + { 12 + char type, name[500]; 13 + __u64 addr, res = 0; 14 + FILE *f; 15 + 16 + f = fopen("/proc/kallsyms", "r"); 17 + if (CHECK(!f, "kallsyms_fopen", "failed to open: %d\n", errno)) 18 + return 0; 19 + 20 + while (fscanf(f, "%llx %c %499s%*[^\n]\n", &addr, &type, name) > 0) { 21 + if (strcmp(name, sym) == 0) { 22 + res = addr; 23 + goto out; 24 + } 25 + } 26 + 27 + CHECK(false, "not_found", "symbol %s not found\n", sym); 28 + out: 29 + fclose(f); 30 + return res; 31 + } 32 + 33 + void test_ksyms(void) 34 + { 35 + __u64 link_fops_addr = kallsyms_find("bpf_link_fops"); 36 + const char *btf_path = "/sys/kernel/btf/vmlinux"; 37 + struct test_ksyms *skel; 38 + struct test_ksyms__data *data; 39 + struct stat st; 40 + __u64 btf_size; 41 + int err; 42 + 43 + if (CHECK(stat(btf_path, &st), "stat_btf", "err %d\n", errno)) 44 + return; 45 + btf_size = st.st_size; 46 + 47 + skel = test_ksyms__open_and_load(); 48 + if (CHECK(!skel, "skel_open", "failed to open and load skeleton\n")) 49 + return; 50 + 51 + err = test_ksyms__attach(skel); 52 + if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err)) 53 + goto cleanup; 54 + 55 + /* trigger tracepoint */ 56 + usleep(1); 57 + 58 + data = skel->data; 59 + CHECK(data->out__bpf_link_fops != link_fops_addr, "bpf_link_fops", 60 + "got 0x%llx, exp 0x%llx\n", 61 + data->out__bpf_link_fops, link_fops_addr); 62 + CHECK(data->out__bpf_link_fops1 != 0, "bpf_link_fops1", 63 + "got %llu, exp %llu\n", data->out__bpf_link_fops1, (__u64)0); 64 + CHECK(data->out__btf_size != btf_size, "btf_size", 65 + "got %llu, exp %llu\n", data->out__btf_size, btf_size); 66 + CHECK(data->out__per_cpu_start != 0, "__per_cpu_start", 67 + "got %llu, exp %llu\n", data->out__per_cpu_start, (__u64)0); 68 + 69 + cleanup: 70 + test_ksyms__destroy(skel); 71 + }
+32
tools/testing/selftests/bpf/progs/test_ksyms.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2019 Facebook */ 3 + 4 + #include <stdbool.h> 5 + #include <linux/bpf.h> 6 + #include <bpf/bpf_helpers.h> 7 + 8 + __u64 out__bpf_link_fops = -1; 9 + __u64 out__bpf_link_fops1 = -1; 10 + __u64 out__btf_size = -1; 11 + __u64 out__per_cpu_start = -1; 12 + 13 + extern const void bpf_link_fops __ksym; 14 + extern const void __start_BTF __ksym; 15 + extern const void __stop_BTF __ksym; 16 + extern const void __per_cpu_start __ksym; 17 + /* non-existing symbol, weak, default to zero */ 18 + extern const void bpf_link_fops1 __ksym __weak; 19 + 20 + SEC("raw_tp/sys_enter") 21 + int handler(const void *ctx) 22 + { 23 + out__bpf_link_fops = (__u64)&bpf_link_fops; 24 + out__btf_size = (__u64)(&__stop_BTF - &__start_BTF); 25 + out__per_cpu_start = (__u64)&__per_cpu_start; 26 + 27 + out__bpf_link_fops1 = (__u64)&bpf_link_fops1; 28 + 29 + return 0; 30 + } 31 + 32 + char _license[] SEC("license") = "GPL";