0001
0002
0003
0004 #include "btf_ptr.h"
0005 #include <bpf/bpf_helpers.h>
0006 #include <bpf/bpf_tracing.h>
0007 #include <bpf/bpf_core_read.h>
0008
0009 #include <errno.h>
0010
0011 long ret = 0;
0012 int num_subtests = 0;
0013 int ran_subtests = 0;
0014 bool skip = false;
0015
0016 #define STRSIZE 2048
0017 #define EXPECTED_STRSIZE 256
0018
0019 #if defined(bpf_target_s390)
0020
0021 #define BADPTR ((void *)0xFFFFFFFFFFFFF000ULL)
0022 #else
0023 #define BADPTR 0
0024 #endif
0025
0026 #ifndef ARRAY_SIZE
0027 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
0028 #endif
0029
0030 struct {
0031 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0032 __uint(max_entries, 1);
0033 __type(key, __u32);
0034 __type(value, char[STRSIZE]);
0035 } strdata SEC(".maps");
0036
0037 static int __strncmp(const void *m1, const void *m2, size_t len)
0038 {
0039 const unsigned char *s1 = m1;
0040 const unsigned char *s2 = m2;
0041 int i, delta = 0;
0042
0043 for (i = 0; i < len; i++) {
0044 delta = s1[i] - s2[i];
0045 if (delta || s1[i] == 0 || s2[i] == 0)
0046 break;
0047 }
0048 return delta;
0049 }
0050
0051 #if __has_builtin(__builtin_btf_type_id)
0052 #define TEST_BTF(_str, _type, _flags, _expected, ...) \
0053 do { \
0054 static const char _expectedval[EXPECTED_STRSIZE] = \
0055 _expected; \
0056 static const char _ptrtype[64] = #_type; \
0057 __u64 _hflags = _flags | BTF_F_COMPACT; \
0058 static _type _ptrdata = __VA_ARGS__; \
0059 static struct btf_ptr _ptr = { }; \
0060 int _cmp; \
0061 \
0062 ++num_subtests; \
0063 if (ret < 0) \
0064 break; \
0065 ++ran_subtests; \
0066 _ptr.ptr = &_ptrdata; \
0067 _ptr.type_id = bpf_core_type_id_kernel(_type); \
0068 if (_ptr.type_id <= 0) { \
0069 ret = -EINVAL; \
0070 break; \
0071 } \
0072 ret = bpf_snprintf_btf(_str, STRSIZE, \
0073 &_ptr, sizeof(_ptr), _hflags); \
0074 if (ret) \
0075 break; \
0076 _cmp = __strncmp(_str, _expectedval, EXPECTED_STRSIZE); \
0077 if (_cmp != 0) { \
0078 bpf_printk("(%d) got %s", _cmp, _str); \
0079 bpf_printk("(%d) expected %s", _cmp, \
0080 _expectedval); \
0081 ret = -EBADMSG; \
0082 break; \
0083 } \
0084 } while (0)
0085 #endif
0086
0087
0088 #define TEST_BTF_C(_str, _type, _flags, ...) \
0089 TEST_BTF(_str, _type, _flags, "(" #_type ")" #__VA_ARGS__, \
0090 __VA_ARGS__)
0091
0092
0093
0094
0095 SEC("tp_btf/netif_receive_skb")
0096 int BPF_PROG(trace_netif_receive_skb, struct sk_buff *skb)
0097 {
0098 static __u64 flags[] = { 0, BTF_F_COMPACT, BTF_F_ZERO, BTF_F_PTR_RAW,
0099 BTF_F_NONAME, BTF_F_COMPACT | BTF_F_ZERO |
0100 BTF_F_PTR_RAW | BTF_F_NONAME };
0101 static struct btf_ptr p = { };
0102 __u32 key = 0;
0103 int i, __ret;
0104 char *str;
0105
0106 #if __has_builtin(__builtin_btf_type_id)
0107 str = bpf_map_lookup_elem(&strdata, &key);
0108 if (!str)
0109 return 0;
0110
0111
0112 p.type_id = bpf_core_type_id_kernel(struct sk_buff);
0113 p.ptr = skb;
0114 for (i = 0; i < ARRAY_SIZE(flags); i++) {
0115 ++num_subtests;
0116 ret = bpf_snprintf_btf(str, STRSIZE, &p, sizeof(p), 0);
0117 if (ret < 0)
0118 bpf_printk("returned %d when writing skb", ret);
0119 ++ran_subtests;
0120 }
0121
0122
0123 p.ptr = BADPTR;
0124 __ret = bpf_snprintf_btf(str, STRSIZE, &p, sizeof(p), 0);
0125 if (__ret >= 0) {
0126 bpf_printk("printing %llx should generate error, got (%d)",
0127 (unsigned long long)BADPTR, __ret);
0128 ret = -ERANGE;
0129 }
0130
0131
0132
0133
0134 TEST_BTF_C(str, int, 0, 1234);
0135 TEST_BTF(str, int, BTF_F_NONAME, "1234", 1234);
0136
0137 TEST_BTF(str, int, 0, "(int)0", 0);
0138 TEST_BTF(str, int, BTF_F_NONAME, "0", 0);
0139 TEST_BTF(str, int, BTF_F_ZERO, "(int)0", 0);
0140 TEST_BTF(str, int, BTF_F_NONAME | BTF_F_ZERO, "0", 0);
0141 TEST_BTF_C(str, int, 0, -4567);
0142 TEST_BTF(str, int, BTF_F_NONAME, "-4567", -4567);
0143
0144
0145 TEST_BTF_C(str, char, 0, 100);
0146 TEST_BTF(str, char, BTF_F_NONAME, "100", 100);
0147
0148 TEST_BTF(str, char, 0, "(char)0", 0);
0149 TEST_BTF(str, char, BTF_F_NONAME, "0", 0);
0150 TEST_BTF(str, char, BTF_F_ZERO, "(char)0", 0);
0151 TEST_BTF(str, char, BTF_F_NONAME | BTF_F_ZERO, "0", 0);
0152
0153
0154 TEST_BTF_C(str, uint64_t, 0, 100);
0155 TEST_BTF(str, u64, BTF_F_NONAME, "1", 1);
0156
0157 TEST_BTF(str, u64, 0, "(u64)0", 0);
0158 TEST_BTF(str, u64, BTF_F_NONAME, "0", 0);
0159 TEST_BTF(str, u64, BTF_F_ZERO, "(u64)0", 0);
0160 TEST_BTF(str, u64, BTF_F_NONAME|BTF_F_ZERO, "0", 0);
0161
0162
0163 TEST_BTF_C(str, atomic_t, 0, {.counter = (int)1,});
0164 TEST_BTF(str, atomic_t, BTF_F_NONAME, "{1,}", {.counter = 1,});
0165
0166 TEST_BTF(str, atomic_t, 0, "(atomic_t){}", {.counter = 0,});
0167 TEST_BTF(str, atomic_t, BTF_F_NONAME, "{}", {.counter = 0,});
0168 TEST_BTF(str, atomic_t, BTF_F_ZERO, "(atomic_t){.counter = (int)0,}",
0169 {.counter = 0,});
0170 TEST_BTF(str, atomic_t, BTF_F_NONAME|BTF_F_ZERO,
0171 "{0,}", {.counter = 0,});
0172
0173
0174 TEST_BTF_C(str, enum bpf_cmd, 0, BPF_MAP_CREATE);
0175 TEST_BTF(str, enum bpf_cmd, 0, "(enum bpf_cmd)BPF_MAP_CREATE", 0);
0176 TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME, "BPF_MAP_CREATE",
0177 BPF_MAP_CREATE);
0178 TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME|BTF_F_ZERO,
0179 "BPF_MAP_CREATE", 0);
0180
0181 TEST_BTF(str, enum bpf_cmd, BTF_F_ZERO, "(enum bpf_cmd)BPF_MAP_CREATE",
0182 BPF_MAP_CREATE);
0183 TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME|BTF_F_ZERO,
0184 "BPF_MAP_CREATE", BPF_MAP_CREATE);
0185 TEST_BTF_C(str, enum bpf_cmd, 0, 2000);
0186 TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME, "2000", 2000);
0187
0188
0189 TEST_BTF_C(str, struct btf_enum, 0,
0190 {.name_off = (__u32)3,.val = (__s32)-1,});
0191 TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{3,-1,}",
0192 { .name_off = 3, .val = -1,});
0193 TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{-1,}",
0194 { .name_off = 0, .val = -1,});
0195 TEST_BTF(str, struct btf_enum, BTF_F_NONAME|BTF_F_ZERO, "{0,-1,}",
0196 { .name_off = 0, .val = -1,});
0197
0198 TEST_BTF(str, struct btf_enum, 0, "(struct btf_enum){}",
0199 { .name_off = 0, .val = 0,});
0200 TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{}",
0201 { .name_off = 0, .val = 0,});
0202 TEST_BTF(str, struct btf_enum, BTF_F_ZERO,
0203 "(struct btf_enum){.name_off = (__u32)0,.val = (__s32)0,}",
0204 { .name_off = 0, .val = 0,});
0205
0206
0207 TEST_BTF(str, struct list_head, BTF_F_PTR_RAW,
0208 "(struct list_head){.next = (struct list_head *)0x0000000000000001,}",
0209 { .next = (struct list_head *)1 });
0210
0211 TEST_BTF(str, struct list_head, BTF_F_PTR_RAW,
0212 "(struct list_head){}",
0213 { .next = (struct list_head *)0 });
0214
0215
0216 TEST_BTF(str, struct bpf_prog_info, 0,
0217 "(struct bpf_prog_info){.name = (char[])['f','o','o',],}",
0218 { .name = "foo",});
0219 TEST_BTF(str, struct bpf_prog_info, BTF_F_NONAME,
0220 "{['f','o','o',],}",
0221 {.name = "foo",});
0222
0223 TEST_BTF(str, struct bpf_prog_info, 0,
0224 "(struct bpf_prog_info){}",
0225 {.name = {'\0', 'f', 'o', 'o'}});
0226
0227 TEST_BTF(str, struct bpf_prog_info, 0,
0228 "(struct bpf_prog_info){.name = (char[])[1,2,3,],}",
0229 { .name = {1, 2, 3, 0}});
0230
0231
0232 TEST_BTF(str, struct __sk_buff, 0,
0233 "(struct __sk_buff){.cb = (__u32[])[1,2,3,4,5,],}",
0234 { .cb = {1, 2, 3, 4, 5,},});
0235 TEST_BTF(str, struct __sk_buff, BTF_F_NONAME,
0236 "{[1,2,3,4,5,],}",
0237 { .cb = { 1, 2, 3, 4, 5},});
0238
0239 TEST_BTF(str, struct __sk_buff, 0,
0240 "(struct __sk_buff){.cb = (__u32[])[1,],}",
0241 { .cb = { 0, 0, 1, 0, 0},});
0242
0243
0244 TEST_BTF_C(str, struct bpf_insn, 0,
0245 {.code = (__u8)1,.dst_reg = (__u8)0x2,.src_reg = (__u8)0x3,.off = (__s16)4,.imm = (__s32)5,});
0246 TEST_BTF(str, struct bpf_insn, BTF_F_NONAME, "{1,0x2,0x3,4,5,}",
0247 {.code = 1, .dst_reg = 0x2, .src_reg = 0x3, .off = 4,
0248 .imm = 5,});
0249 #else
0250 skip = true;
0251 #endif
0252
0253 return 0;
0254 }
0255
0256 char _license[] SEC("license") = "GPL";