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

selftests/bpf: Test for btf_load command.

Improve selftest to check that btf_load is working from bpf program.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20210514003623.28033-8-alexei.starovoitov@gmail.com

authored by

Alexei Starovoitov and committed by
Daniel Borkmann
2341d6bb c571bd75

+53
+3
tools/testing/selftests/bpf/prog_tests/syscall.c
··· 9 9 int max_entries; 10 10 int map_fd; 11 11 int prog_fd; 12 + int btf_fd; 12 13 }; 13 14 14 15 void test_syscall(void) ··· 50 49 close(ctx.prog_fd); 51 50 if (ctx.map_fd > 0) 52 51 close(ctx.map_fd); 52 + if (ctx.btf_fd > 0) 53 + close(ctx.btf_fd); 53 54 }
+50
tools/testing/selftests/bpf/progs/syscall.c
··· 5 5 #include <bpf/bpf_helpers.h> 6 6 #include <bpf/bpf_tracing.h> 7 7 #include <../../../tools/include/linux/filter.h> 8 + #include <linux/btf.h> 8 9 9 10 char _license[] SEC("license") = "GPL"; 10 11 ··· 15 14 int max_entries; 16 15 int map_fd; 17 16 int prog_fd; 17 + int btf_fd; 18 18 }; 19 + 20 + #define BTF_INFO_ENC(kind, kind_flag, vlen) \ 21 + ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) 22 + #define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type) 23 + #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \ 24 + ((encoding) << 24 | (bits_offset) << 16 | (nr_bits)) 25 + #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \ 26 + BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \ 27 + BTF_INT_ENC(encoding, bits_offset, bits) 28 + 29 + static int btf_load(void) 30 + { 31 + struct btf_blob { 32 + struct btf_header btf_hdr; 33 + __u32 types[8]; 34 + __u32 str; 35 + } raw_btf = { 36 + .btf_hdr = { 37 + .magic = BTF_MAGIC, 38 + .version = BTF_VERSION, 39 + .hdr_len = sizeof(struct btf_header), 40 + .type_len = sizeof(__u32) * 8, 41 + .str_off = sizeof(__u32) * 8, 42 + .str_len = sizeof(__u32), 43 + }, 44 + .types = { 45 + /* long */ 46 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8), /* [1] */ 47 + /* unsigned long */ 48 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 49 + }, 50 + }; 51 + static union bpf_attr btf_load_attr = { 52 + .btf_size = sizeof(raw_btf), 53 + }; 54 + 55 + btf_load_attr.btf = (long)&raw_btf; 56 + return bpf_sys_bpf(BPF_BTF_LOAD, &btf_load_attr, sizeof(btf_load_attr)); 57 + } 19 58 20 59 SEC("syscall") 21 60 int bpf_prog(struct args *ctx) ··· 74 33 .map_type = BPF_MAP_TYPE_HASH, 75 34 .key_size = 8, 76 35 .value_size = 8, 36 + .btf_key_type_id = 1, 37 + .btf_value_type_id = 2, 77 38 }; 78 39 static union bpf_attr map_update_attr = { .map_fd = 1, }; 79 40 static __u64 key = 12; ··· 86 43 }; 87 44 int ret; 88 45 46 + ret = btf_load(); 47 + if (ret <= 0) 48 + return ret; 49 + 50 + ctx->btf_fd = ret; 89 51 map_create_attr.max_entries = ctx->max_entries; 52 + map_create_attr.btf_fd = ret; 53 + 90 54 prog_load_attr.license = (long) license; 91 55 prog_load_attr.insns = (long) insns; 92 56 prog_load_attr.log_buf = ctx->log_buf;