On Thu, Feb 28, 2019 at 3:32 PM Daniel Borkmann <daniel@xxxxxxxxxxxxx> wrote: > > From: Joe Stringer <joe@xxxxxxxxxxx> > > Add tests for libbpf relocation of static variable references > into the .data, .rodata and .bss sections of the ELF. Tests with > different offsets are all passing: > > # ./test_progs > [...] > test_static_data_access:PASS:load program 0 nsec > test_static_data_access:PASS:pass packet 278 nsec > test_static_data_access:PASS:relocate .bss reference 1 278 nsec > test_static_data_access:PASS:relocate .data reference 1 278 nsec > test_static_data_access:PASS:relocate .rodata reference 1 278 nsec > test_static_data_access:PASS:relocate .bss reference 2 278 nsec > test_static_data_access:PASS:relocate .data reference 2 278 nsec > test_static_data_access:PASS:relocate .rodata reference 2 278 nsec > test_static_data_access:PASS:relocate .bss reference 3 278 nsec > test_static_data_access:PASS:relocate .bss reference 4 278 nsec > Summary: 223 PASSED, 0 FAILED > > Joint work with Daniel Borkmann. > > Signed-off-by: Joe Stringer <joe@xxxxxxxxxxx> > Signed-off-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx> > --- > tools/testing/selftests/bpf/bpf_helpers.h | 2 +- > .../selftests/bpf/progs/test_global_data.c | 61 +++++++++++++++++++ > tools/testing/selftests/bpf/test_progs.c | 50 +++++++++++++++ > 3 files changed, 112 insertions(+), 1 deletion(-) > create mode 100644 tools/testing/selftests/bpf/progs/test_global_data.c > > diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h > index d9999f1ed1d2..0463662935f9 100644 > --- a/tools/testing/selftests/bpf/bpf_helpers.h > +++ b/tools/testing/selftests/bpf/bpf_helpers.h > @@ -11,7 +11,7 @@ > /* helper functions called from eBPF programs written in C */ > static void *(*bpf_map_lookup_elem)(void *map, void *key) = > (void *) BPF_FUNC_map_lookup_elem; > -static int (*bpf_map_update_elem)(void *map, void *key, void *value, > +static int (*bpf_map_update_elem)(void *map, const void *key, const void *value, > unsigned long long flags) = > (void *) BPF_FUNC_map_update_elem; > static int (*bpf_map_delete_elem)(void *map, void *key) = > diff --git a/tools/testing/selftests/bpf/progs/test_global_data.c b/tools/testing/selftests/bpf/progs/test_global_data.c > new file mode 100644 > index 000000000000..2a7cf40b8efb > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/test_global_data.c > @@ -0,0 +1,61 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// Copyright (c) 2019 Isovalent, Inc. > + > +#include <linux/bpf.h> > +#include <linux/pkt_cls.h> > +#include <string.h> > + > +#include "bpf_helpers.h" > + > +struct bpf_map_def SEC("maps") result = { > + .type = BPF_MAP_TYPE_ARRAY, > + .key_size = sizeof(__u32), > + .value_size = sizeof(__u64), > + .max_entries = 9, > +}; > + > +static __u64 static_bss = 0; /* Reloc reference to .bss section */ > +static __u64 static_data = 42; /* Reloc reference to .data section */ > +static const __u64 static_rodata = 24; /* Reloc reference to .rodata section */ > +static __u64 static_bss2 = 0; /* Reloc reference to .bss section */ > +static __u64 static_data2 = 0xffeeff; /* Reloc reference to .data section */ > +static const __u64 static_rodata2 = 0xabab; /* Reloc reference to .rodata section */ > +static const __u64 static_rodata3 = 0xab; /* Reloc reference to .rodata section */ In the light of Yonghong's explanation about static vs non-static globals, it would be nice to add test for non-static initialized globals here as well? > + > +SEC("static_data_load") > +int load_static_data(struct __sk_buff *skb) > +{ > + __u32 key; > + > + key = 0; > + bpf_map_update_elem(&result, &key, &static_bss, 0); > + > + key = 1; > + bpf_map_update_elem(&result, &key, &static_data, 0); > + > + key = 2; > + bpf_map_update_elem(&result, &key, &static_rodata, 0); > + > + key = 3; > + bpf_map_update_elem(&result, &key, &static_bss2, 0); > + > + key = 4; > + bpf_map_update_elem(&result, &key, &static_data2, 0); > + > + key = 5; > + bpf_map_update_elem(&result, &key, &static_rodata2, 0); > + > + key = 6; > + static_bss2 = 1234; > + bpf_map_update_elem(&result, &key, &static_bss2, 0); > + > + key = 7; > + bpf_map_update_elem(&result, &key, &static_bss, 0); > + > + key = 8; > + bpf_map_update_elem(&result, &key, &static_rodata3, 0); > + > + return TC_ACT_OK; > +} > + > +char _license[] SEC("license") = "GPL"; > diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c > index c59d2e015d16..a3e64c054572 100644 > --- a/tools/testing/selftests/bpf/test_progs.c > +++ b/tools/testing/selftests/bpf/test_progs.c > @@ -738,6 +738,55 @@ static void test_pkt_md_access(void) > bpf_object__close(obj); > } > > +static void test_static_data_access(void) > +{ > + const char *file = "./test_global_data.o"; > + struct bpf_object *obj; > + __u32 duration = 0, retval; > + int i, err, prog_fd, map_fd; > + uint64_t value; > + > + err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); > + if (CHECK(err, "load program", "error %d loading %s\n", err, file)) > + return; > + > + map_fd = bpf_find_map(__func__, obj, "result"); > + if (map_fd < 0) { > + error_cnt++; > + goto close_prog; > + } > + > + err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), > + NULL, NULL, &retval, &duration); > + CHECK(err || retval, "pass packet", > + "err %d errno %d retval %d duration %d\n", > + err, errno, retval, duration); > + > + struct { > + char *name; > + uint32_t key; > + uint64_t value; > + } tests[] = { > + { "relocate .bss reference 1", 0, 0 }, > + { "relocate .data reference 1", 1, 42 }, > + { "relocate .rodata reference 1", 2, 24 }, > + { "relocate .bss reference 2", 3, 0 }, > + { "relocate .data reference 2", 4, 0xffeeff }, > + { "relocate .rodata reference 2", 5, 0xabab }, > + { "relocate .bss reference 3", 6, 1234 }, > + { "relocate .bss reference 4", 7, 0 }, > + }; > + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { > + err = bpf_map_lookup_elem(map_fd, &tests[i].key, &value); > + CHECK (err || value != tests[i].value, tests[i].name, > + "err %d result %lu expected %lu\n", > + err, value, tests[i].value); > + } > + > +close_prog: > + bpf_object__close(obj); > +} > + > static void test_obj_name(void) > { > struct { > @@ -2182,6 +2231,7 @@ int main(void) > test_map_lock(); > test_signal_pending(BPF_PROG_TYPE_SOCKET_FILTER); > test_signal_pending(BPF_PROG_TYPE_FLOW_DISSECTOR); > + test_static_data_access(); > > printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); > return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; > -- > 2.17.1 >