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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'libbpf: support loading/storing any BTF'

Andrii Nakryiko says:

====================
Add support for loading and storing BTF in either little- or big-endian
integer encodings, regardless of host endianness. This allows users of libbpf
to not care about endianness when they don't want to and transparently
open/load BTF of any endianness. libbpf will preserve original endianness and
will convert output raw data as necessary back to original endianness, if
necessary. This allows tools like pahole to be ignorant to such issues during
cross-compilation.

While working with BTF data in memory, the endianness is always native to the
host. Convetion can happen only during btf__get_raw_data() call, and only in
a raw data copy.

Additionally, it's possible to force output BTF endianness through new
btf__set_endianness() API. This which allows to create flexible tools doing
arbitrary conversions of BTF endianness, just by relying on libbpf.

Cc: Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com>
Cc: Tony Ambardar <tony.ambardar@gmail.com>
Cc: Ilya Leoshkevich <iii@linux.ibm.com>
Cc: Luka Perkov <luka.perkov@sartura.hr>
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+420 -99
+247 -65
tools/lib/bpf/btf.c
··· 1 1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 2 /* Copyright (c) 2018 Facebook */ 3 3 4 + #include <byteswap.h> 4 5 #include <endian.h> 5 6 #include <stdio.h> 6 7 #include <stdlib.h> ··· 28 27 static struct btf_type btf_void; 29 28 30 29 struct btf { 30 + /* raw BTF data in native endianness */ 31 31 void *raw_data; 32 + /* raw BTF data in non-native endianness */ 33 + void *raw_data_swapped; 32 34 __u32 raw_size; 35 + /* whether target endianness differs from the native one */ 36 + bool swapped_endian; 33 37 34 38 /* 35 39 * When BTF is loaded from an ELF or raw memory it is stored ··· 159 153 return 0; 160 154 } 161 155 156 + static void btf_bswap_hdr(struct btf_header *h) 157 + { 158 + h->magic = bswap_16(h->magic); 159 + h->hdr_len = bswap_32(h->hdr_len); 160 + h->type_off = bswap_32(h->type_off); 161 + h->type_len = bswap_32(h->type_len); 162 + h->str_off = bswap_32(h->str_off); 163 + h->str_len = bswap_32(h->str_len); 164 + } 165 + 162 166 static int btf_parse_hdr(struct btf *btf) 163 167 { 164 - const struct btf_header *hdr = btf->hdr; 168 + struct btf_header *hdr = btf->hdr; 165 169 __u32 meta_left; 166 170 167 171 if (btf->raw_size < sizeof(struct btf_header)) { ··· 179 163 return -EINVAL; 180 164 } 181 165 182 - if (hdr->magic != BTF_MAGIC) { 166 + if (hdr->magic == bswap_16(BTF_MAGIC)) { 167 + btf->swapped_endian = true; 168 + if (bswap_32(hdr->hdr_len) != sizeof(struct btf_header)) { 169 + pr_warn("Can't load BTF with non-native endianness due to unsupported header length %u\n", 170 + bswap_32(hdr->hdr_len)); 171 + return -ENOTSUP; 172 + } 173 + btf_bswap_hdr(hdr); 174 + } else if (hdr->magic != BTF_MAGIC) { 183 175 pr_debug("Invalid BTF magic:%x\n", hdr->magic); 184 176 return -EINVAL; 185 - } 186 - 187 - if (hdr->version != BTF_VERSION) { 188 - pr_debug("Unsupported BTF version:%u\n", hdr->version); 189 - return -ENOTSUP; 190 - } 191 - 192 - if (hdr->flags) { 193 - pr_debug("Unsupported BTF flags:%x\n", hdr->flags); 194 - return -ENOTSUP; 195 177 } 196 178 197 179 meta_left = btf->raw_size - sizeof(*hdr); ··· 238 224 239 225 static int btf_type_size(const struct btf_type *t) 240 226 { 241 - int base_size = sizeof(struct btf_type); 227 + const int base_size = sizeof(struct btf_type); 242 228 __u16 vlen = btf_vlen(t); 243 229 244 230 switch (btf_kind(t)) { ··· 271 257 } 272 258 } 273 259 260 + static void btf_bswap_type_base(struct btf_type *t) 261 + { 262 + t->name_off = bswap_32(t->name_off); 263 + t->info = bswap_32(t->info); 264 + t->type = bswap_32(t->type); 265 + } 266 + 267 + static int btf_bswap_type_rest(struct btf_type *t) 268 + { 269 + struct btf_var_secinfo *v; 270 + struct btf_member *m; 271 + struct btf_array *a; 272 + struct btf_param *p; 273 + struct btf_enum *e; 274 + __u16 vlen = btf_vlen(t); 275 + int i; 276 + 277 + switch (btf_kind(t)) { 278 + case BTF_KIND_FWD: 279 + case BTF_KIND_CONST: 280 + case BTF_KIND_VOLATILE: 281 + case BTF_KIND_RESTRICT: 282 + case BTF_KIND_PTR: 283 + case BTF_KIND_TYPEDEF: 284 + case BTF_KIND_FUNC: 285 + return 0; 286 + case BTF_KIND_INT: 287 + *(__u32 *)(t + 1) = bswap_32(*(__u32 *)(t + 1)); 288 + return 0; 289 + case BTF_KIND_ENUM: 290 + for (i = 0, e = btf_enum(t); i < vlen; i++, e++) { 291 + e->name_off = bswap_32(e->name_off); 292 + e->val = bswap_32(e->val); 293 + } 294 + return 0; 295 + case BTF_KIND_ARRAY: 296 + a = btf_array(t); 297 + a->type = bswap_32(a->type); 298 + a->index_type = bswap_32(a->index_type); 299 + a->nelems = bswap_32(a->nelems); 300 + return 0; 301 + case BTF_KIND_STRUCT: 302 + case BTF_KIND_UNION: 303 + for (i = 0, m = btf_members(t); i < vlen; i++, m++) { 304 + m->name_off = bswap_32(m->name_off); 305 + m->type = bswap_32(m->type); 306 + m->offset = bswap_32(m->offset); 307 + } 308 + return 0; 309 + case BTF_KIND_FUNC_PROTO: 310 + for (i = 0, p = btf_params(t); i < vlen; i++, p++) { 311 + p->name_off = bswap_32(p->name_off); 312 + p->type = bswap_32(p->type); 313 + } 314 + return 0; 315 + case BTF_KIND_VAR: 316 + btf_var(t)->linkage = bswap_32(btf_var(t)->linkage); 317 + return 0; 318 + case BTF_KIND_DATASEC: 319 + for (i = 0, v = btf_var_secinfos(t); i < vlen; i++, v++) { 320 + v->type = bswap_32(v->type); 321 + v->offset = bswap_32(v->offset); 322 + v->size = bswap_32(v->size); 323 + } 324 + return 0; 325 + default: 326 + pr_debug("Unsupported BTF_KIND:%u\n", btf_kind(t)); 327 + return -EINVAL; 328 + } 329 + } 330 + 274 331 static int btf_parse_type_sec(struct btf *btf) 275 332 { 276 333 struct btf_header *hdr = btf->hdr; 277 334 void *next_type = btf->types_data; 278 335 void *end_type = next_type + hdr->type_len; 279 - int err, type_size; 336 + int err, i, type_size; 280 337 281 338 /* VOID (type_id == 0) is specially handled by btf__get_type_by_id(), 282 339 * so ensure we can never properly use its offset from index by ··· 357 272 if (err) 358 273 return err; 359 274 360 - while (next_type < end_type) { 361 - err = btf_add_type_idx_entry(btf, next_type - btf->types_data); 362 - if (err) 363 - return err; 275 + while (next_type + sizeof(struct btf_type) <= end_type) { 276 + i++; 277 + 278 + if (btf->swapped_endian) 279 + btf_bswap_type_base(next_type); 364 280 365 281 type_size = btf_type_size(next_type); 366 282 if (type_size < 0) 367 283 return type_size; 284 + if (next_type + type_size > end_type) { 285 + pr_warn("BTF type [%d] is malformed\n", i); 286 + return -EINVAL; 287 + } 288 + 289 + if (btf->swapped_endian && btf_bswap_type_rest(next_type)) 290 + return -EINVAL; 291 + 292 + err = btf_add_type_idx_entry(btf, next_type - btf->types_data); 293 + if (err) 294 + return err; 368 295 369 296 next_type += type_size; 370 297 btf->nr_types++; 298 + } 299 + 300 + if (next_type != end_type) { 301 + pr_warn("BTF types data is malformed\n"); 302 + return -EINVAL; 371 303 } 372 304 373 305 return 0; ··· 472 370 if (ptr_sz != 4 && ptr_sz != 8) 473 371 return -EINVAL; 474 372 btf->ptr_sz = ptr_sz; 373 + return 0; 374 + } 375 + 376 + static bool is_host_big_endian(void) 377 + { 378 + #if __BYTE_ORDER == __LITTLE_ENDIAN 379 + return false; 380 + #elif __BYTE_ORDER == __BIG_ENDIAN 381 + return true; 382 + #else 383 + # error "Unrecognized __BYTE_ORDER__" 384 + #endif 385 + } 386 + 387 + enum btf_endianness btf__endianness(const struct btf *btf) 388 + { 389 + if (is_host_big_endian()) 390 + return btf->swapped_endian ? BTF_LITTLE_ENDIAN : BTF_BIG_ENDIAN; 391 + else 392 + return btf->swapped_endian ? BTF_BIG_ENDIAN : BTF_LITTLE_ENDIAN; 393 + } 394 + 395 + int btf__set_endianness(struct btf *btf, enum btf_endianness endian) 396 + { 397 + if (endian != BTF_LITTLE_ENDIAN && endian != BTF_BIG_ENDIAN) 398 + return -EINVAL; 399 + 400 + btf->swapped_endian = is_host_big_endian() != (endian == BTF_BIG_ENDIAN); 401 + if (!btf->swapped_endian) { 402 + free(btf->raw_data_swapped); 403 + btf->raw_data_swapped = NULL; 404 + } 475 405 return 0; 476 406 } 477 407 ··· 695 561 free(btf->strs_data); 696 562 } 697 563 free(btf->raw_data); 564 + free(btf->raw_data_swapped); 698 565 free(btf->type_offs); 699 566 free(btf); 700 567 } ··· 707 572 btf = calloc(1, sizeof(*btf)); 708 573 if (!btf) 709 574 return ERR_PTR(-ENOMEM); 575 + 710 576 btf->fd = -1; 711 577 btf->ptr_sz = sizeof(void *); 578 + btf->swapped_endian = false; 712 579 713 580 /* +1 for empty string at offset 0 */ 714 581 btf->raw_size = sizeof(struct btf_header) + 1; ··· 741 604 if (!btf) 742 605 return ERR_PTR(-ENOMEM); 743 606 744 - btf->fd = -1; 745 - 746 607 btf->raw_data = malloc(size); 747 608 if (!btf->raw_data) { 748 609 err = -ENOMEM; ··· 759 624 760 625 err = btf_parse_str_sec(btf); 761 626 err = err ?: btf_parse_type_sec(btf); 627 + if (err) 628 + goto done; 629 + 630 + btf->fd = -1; 762 631 763 632 done: 764 633 if (err) { ··· 771 632 } 772 633 773 634 return btf; 774 - } 775 - 776 - static bool btf_check_endianness(const GElf_Ehdr *ehdr) 777 - { 778 - #if __BYTE_ORDER == __LITTLE_ENDIAN 779 - return ehdr->e_ident[EI_DATA] == ELFDATA2LSB; 780 - #elif __BYTE_ORDER == __BIG_ENDIAN 781 - return ehdr->e_ident[EI_DATA] == ELFDATA2MSB; 782 - #else 783 - # error "Unrecognized __BYTE_ORDER__" 784 - #endif 785 635 } 786 636 787 637 struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext) ··· 803 675 } 804 676 if (!gelf_getehdr(elf, &ehdr)) { 805 677 pr_warn("failed to get EHDR from %s\n", path); 806 - goto done; 807 - } 808 - if (!btf_check_endianness(&ehdr)) { 809 - pr_warn("non-native ELF endianness is not supported\n"); 810 678 goto done; 811 679 } 812 680 if (!elf_rawdata(elf_getscn(elf, ehdr.e_shstrndx), NULL)) { ··· 916 792 err = -EIO; 917 793 goto err_out; 918 794 } 919 - if (magic != BTF_MAGIC) { 795 + if (magic != BTF_MAGIC && magic != bswap_16(BTF_MAGIC)) { 920 796 /* definitely not a raw BTF */ 921 797 err = -EPROTO; 922 798 goto err_out; ··· 1066 942 return err; 1067 943 } 1068 944 945 + static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endian); 946 + 1069 947 int btf__load(struct btf *btf) 1070 948 { 1071 949 __u32 log_buf_size = 0, raw_size; 1072 950 char *log_buf = NULL; 1073 - const void *raw_data; 951 + void *raw_data; 1074 952 int err = 0; 1075 953 1076 954 if (btf->fd >= 0) ··· 1087 961 *log_buf = 0; 1088 962 } 1089 963 1090 - raw_data = btf__get_raw_data(btf, &raw_size); 964 + raw_data = btf_get_raw_data(btf, &raw_size, false); 1091 965 if (!raw_data) { 1092 966 err = -ENOMEM; 1093 967 goto done; 1094 968 } 969 + /* cache native raw data representation */ 970 + btf->raw_size = raw_size; 971 + btf->raw_data = raw_data; 1095 972 1096 973 btf->fd = bpf_load_btf(raw_data, raw_size, log_buf, log_buf_size, false); 1097 974 if (btf->fd < 0) { ··· 1127 998 btf->fd = fd; 1128 999 } 1129 1000 1001 + static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endian) 1002 + { 1003 + struct btf_header *hdr = btf->hdr; 1004 + struct btf_type *t; 1005 + void *data, *p; 1006 + __u32 data_sz; 1007 + int i; 1008 + 1009 + data = swap_endian ? btf->raw_data_swapped : btf->raw_data; 1010 + if (data) { 1011 + *size = btf->raw_size; 1012 + return data; 1013 + } 1014 + 1015 + data_sz = hdr->hdr_len + hdr->type_len + hdr->str_len; 1016 + data = calloc(1, data_sz); 1017 + if (!data) 1018 + return NULL; 1019 + p = data; 1020 + 1021 + memcpy(p, hdr, hdr->hdr_len); 1022 + if (swap_endian) 1023 + btf_bswap_hdr(p); 1024 + p += hdr->hdr_len; 1025 + 1026 + memcpy(p, btf->types_data, hdr->type_len); 1027 + if (swap_endian) { 1028 + for (i = 1; i <= btf->nr_types; i++) { 1029 + t = p + btf->type_offs[i]; 1030 + /* btf_bswap_type_rest() relies on native t->info, so 1031 + * we swap base type info after we swapped all the 1032 + * additional information 1033 + */ 1034 + if (btf_bswap_type_rest(t)) 1035 + goto err_out; 1036 + btf_bswap_type_base(t); 1037 + } 1038 + } 1039 + p += hdr->type_len; 1040 + 1041 + memcpy(p, btf->strs_data, hdr->str_len); 1042 + p += hdr->str_len; 1043 + 1044 + *size = data_sz; 1045 + return data; 1046 + err_out: 1047 + free(data); 1048 + return NULL; 1049 + } 1050 + 1130 1051 const void *btf__get_raw_data(const struct btf *btf_ro, __u32 *size) 1131 1052 { 1132 1053 struct btf *btf = (struct btf *)btf_ro; 1054 + __u32 data_sz; 1055 + void *data; 1133 1056 1134 - if (!btf->raw_data) { 1135 - struct btf_header *hdr = btf->hdr; 1136 - void *data; 1057 + data = btf_get_raw_data(btf, &data_sz, btf->swapped_endian); 1058 + if (!data) 1059 + return NULL; 1137 1060 1138 - btf->raw_size = hdr->hdr_len + hdr->type_len + hdr->str_len; 1139 - btf->raw_data = calloc(1, btf->raw_size); 1140 - if (!btf->raw_data) 1141 - return NULL; 1142 - data = btf->raw_data; 1143 - 1144 - memcpy(data, hdr, hdr->hdr_len); 1145 - data += hdr->hdr_len; 1146 - 1147 - memcpy(data, btf->types_data, hdr->type_len); 1148 - data += hdr->type_len; 1149 - 1150 - memcpy(data, btf->strs_data, hdr->str_len); 1151 - data += hdr->str_len; 1152 - } 1153 - *size = btf->raw_size; 1154 - return btf->raw_data; 1061 + btf->raw_size = data_sz; 1062 + if (btf->swapped_endian) 1063 + btf->raw_data_swapped = data; 1064 + else 1065 + btf->raw_data = data; 1066 + *size = data_sz; 1067 + return data; 1155 1068 } 1156 1069 1157 1070 const char *btf__str_by_offset(const struct btf *btf, __u32 offset) ··· 1361 1190 return strcmp(str1, str2) == 0; 1362 1191 } 1363 1192 1193 + static void btf_invalidate_raw_data(struct btf *btf) 1194 + { 1195 + if (btf->raw_data) { 1196 + free(btf->raw_data); 1197 + btf->raw_data = NULL; 1198 + } 1199 + if (btf->raw_data_swapped) { 1200 + free(btf->raw_data_swapped); 1201 + btf->raw_data_swapped = NULL; 1202 + } 1203 + } 1204 + 1364 1205 /* Ensure BTF is ready to be modified (by splitting into a three memory 1365 1206 * regions for header, types, and strings). Also invalidate cached 1366 1207 * raw_data, if any. ··· 1386 1203 1387 1204 if (btf_is_modifiable(btf)) { 1388 1205 /* any BTF modification invalidates raw_data */ 1389 - if (btf->raw_data) { 1390 - free(btf->raw_data); 1391 - btf->raw_data = NULL; 1392 - } 1206 + btf_invalidate_raw_data(btf); 1393 1207 return 0; 1394 1208 } 1395 1209 ··· 1434 1254 btf->strs_deduped = btf->hdr->str_len <= 1; 1435 1255 1436 1256 /* invalidate raw_data representation */ 1437 - free(btf->raw_data); 1438 - btf->raw_data = NULL; 1257 + btf_invalidate_raw_data(btf); 1439 1258 1440 1259 return 0; 1441 1260 ··· 2454 2275 return -EINVAL; 2455 2276 } 2456 2277 2457 - if (hdr->magic != BTF_MAGIC) { 2278 + if (hdr->magic == bswap_16(BTF_MAGIC)) { 2279 + pr_warn("BTF.ext in non-native endianness is not supported\n"); 2280 + return -ENOTSUP; 2281 + } else if (hdr->magic != BTF_MAGIC) { 2458 2282 pr_debug("Invalid BTF.ext magic:%x\n", hdr->magic); 2459 2283 return -EINVAL; 2460 2284 }
+7
tools/lib/bpf/btf.h
··· 25 25 26 26 struct bpf_object; 27 27 28 + enum btf_endianness { 29 + BTF_LITTLE_ENDIAN = 0, 30 + BTF_BIG_ENDIAN = 1, 31 + }; 32 + 28 33 LIBBPF_API void btf__free(struct btf *btf); 29 34 LIBBPF_API struct btf *btf__new(const void *data, __u32 size); 30 35 LIBBPF_API struct btf *btf__new_empty(void); ··· 47 42 __u32 id); 48 43 LIBBPF_API size_t btf__pointer_size(const struct btf *btf); 49 44 LIBBPF_API int btf__set_pointer_size(struct btf *btf, size_t ptr_sz); 45 + LIBBPF_API enum btf_endianness btf__endianness(const struct btf *btf); 46 + LIBBPF_API int btf__set_endianness(struct btf *btf, enum btf_endianness endian); 50 47 LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id); 51 48 LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id); 52 49 LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id);
+2
tools/lib/bpf/libbpf.map
··· 325 325 btf__add_union; 326 326 btf__add_var; 327 327 btf__add_volatile; 328 + btf__endianness; 328 329 btf__find_str; 329 330 btf__new_empty; 331 + btf__set_endianness; 330 332 btf__str_by_offset; 331 333 perf_buffer__buffer_cnt; 332 334 perf_buffer__buffer_fd;
+101
tools/testing/selftests/bpf/prog_tests/btf_endian.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2020 Facebook */ 3 + #define _GNU_SOURCE 4 + #include <string.h> 5 + #include <byteswap.h> 6 + #include <test_progs.h> 7 + #include <bpf/btf.h> 8 + 9 + static int duration = 0; 10 + 11 + void test_btf_endian() { 12 + #if __BYTE_ORDER == __LITTLE_ENDIAN 13 + enum btf_endianness endian = BTF_LITTLE_ENDIAN; 14 + #elif __BYTE_ORDER == __BIG_ENDIAN 15 + enum btf_endianness endian = BTF_BIG_ENDIAN; 16 + #else 17 + #error "Unrecognized __BYTE_ORDER" 18 + #endif 19 + enum btf_endianness swap_endian = 1 - endian; 20 + struct btf *btf = NULL, *swap_btf = NULL; 21 + const void *raw_data, *swap_raw_data; 22 + const struct btf_type *t; 23 + const struct btf_header *hdr; 24 + __u32 raw_sz, swap_raw_sz; 25 + int var_id; 26 + 27 + /* Load BTF in native endianness */ 28 + btf = btf__parse_elf("btf_dump_test_case_syntax.o", NULL); 29 + if (!ASSERT_OK_PTR(btf, "parse_native_btf")) 30 + goto err_out; 31 + 32 + ASSERT_EQ(btf__endianness(btf), endian, "endian"); 33 + btf__set_endianness(btf, swap_endian); 34 + ASSERT_EQ(btf__endianness(btf), swap_endian, "endian"); 35 + 36 + /* Get raw BTF data in non-native endianness... */ 37 + raw_data = btf__get_raw_data(btf, &raw_sz); 38 + if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted")) 39 + goto err_out; 40 + 41 + /* ...and open it as a new BTF instance */ 42 + swap_btf = btf__new(raw_data, raw_sz); 43 + if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf")) 44 + goto err_out; 45 + 46 + ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian"); 47 + ASSERT_EQ(btf__get_nr_types(swap_btf), btf__get_nr_types(btf), "nr_types"); 48 + 49 + swap_raw_data = btf__get_raw_data(swap_btf, &swap_raw_sz); 50 + if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data")) 51 + goto err_out; 52 + 53 + /* both raw data should be identical (with non-native endianness) */ 54 + ASSERT_OK(memcmp(raw_data, swap_raw_data, raw_sz), "mem_identical"); 55 + 56 + /* make sure that at least BTF header data is really swapped */ 57 + hdr = swap_raw_data; 58 + ASSERT_EQ(bswap_16(hdr->magic), BTF_MAGIC, "btf_magic_swapped"); 59 + ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes"); 60 + 61 + /* swap it back to native endianness */ 62 + btf__set_endianness(swap_btf, endian); 63 + swap_raw_data = btf__get_raw_data(swap_btf, &swap_raw_sz); 64 + if (!ASSERT_OK_PTR(swap_raw_data, "swap_raw_data")) 65 + goto err_out; 66 + 67 + /* now header should have native BTF_MAGIC */ 68 + hdr = swap_raw_data; 69 + ASSERT_EQ(hdr->magic, BTF_MAGIC, "btf_magic_native"); 70 + ASSERT_EQ(raw_sz, swap_raw_sz, "raw_sizes"); 71 + 72 + /* now modify original BTF */ 73 + var_id = btf__add_var(btf, "some_var", BTF_VAR_GLOBAL_ALLOCATED, 1); 74 + CHECK(var_id <= 0, "var_id", "failed %d\n", var_id); 75 + 76 + btf__free(swap_btf); 77 + swap_btf = NULL; 78 + 79 + btf__set_endianness(btf, swap_endian); 80 + raw_data = btf__get_raw_data(btf, &raw_sz); 81 + if (!ASSERT_OK_PTR(raw_data, "raw_data_inverted")) 82 + goto err_out; 83 + 84 + /* and re-open swapped raw data again */ 85 + swap_btf = btf__new(raw_data, raw_sz); 86 + if (!ASSERT_OK_PTR(swap_btf, "parse_swap_btf")) 87 + goto err_out; 88 + 89 + ASSERT_EQ(btf__endianness(swap_btf), swap_endian, "endian"); 90 + ASSERT_EQ(btf__get_nr_types(swap_btf), btf__get_nr_types(btf), "nr_types"); 91 + 92 + /* the type should appear as if it was stored in native endianness */ 93 + t = btf__type_by_id(swap_btf, var_id); 94 + ASSERT_STREQ(btf__str_by_offset(swap_btf, t->name_off), "some_var", "var_name"); 95 + ASSERT_EQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_ALLOCATED, "var_linkage"); 96 + ASSERT_EQ(t->type, 1, "var_type"); 97 + 98 + err_out: 99 + btf__free(btf); 100 + btf__free(swap_btf); 101 + }
-34
tools/testing/selftests/bpf/prog_tests/btf_write.c
··· 3 3 #include <test_progs.h> 4 4 #include <bpf/btf.h> 5 5 6 - #define ASSERT_EQ(actual, expected, name) ({ \ 7 - typeof(actual) ___act = (actual); \ 8 - typeof(expected) ___exp = (expected); \ 9 - bool ___ok = ___act == ___exp; \ 10 - CHECK(!___ok, (name), \ 11 - "unexpected %s: actual %lld != expected %lld\n", \ 12 - (name), (long long)(___act), (long long)(___exp)); \ 13 - ___ok; \ 14 - }) 15 - 16 - #define ASSERT_STREQ(actual, expected, name) ({ \ 17 - const char *___act = actual; \ 18 - const char *___exp = expected; \ 19 - bool ___ok = strcmp(___act, ___exp) == 0; \ 20 - CHECK(!___ok, (name), \ 21 - "unexpected %s: actual '%s' != expected '%s'\n", \ 22 - (name), ___act, ___exp); \ 23 - ___ok; \ 24 - }) 25 - 26 - #define ASSERT_OK(res, name) ({ \ 27 - long long ___res = (res); \ 28 - bool ___ok = ___res == 0; \ 29 - CHECK(!___ok, (name), "unexpected error: %lld\n", ___res); \ 30 - ___ok; \ 31 - }) 32 - 33 - #define ASSERT_ERR(res, name) ({ \ 34 - long long ___res = (res); \ 35 - bool ___ok = ___res < 0; \ 36 - CHECK(!___ok, (name), "unexpected success: %lld\n", ___res); \ 37 - ___ok; \ 38 - }) 39 - 40 6 static int duration = 0; 41 7 42 8 void test_btf_write() {
+63
tools/testing/selftests/bpf/test_progs.h
··· 130 130 #define CHECK_ATTR(condition, tag, format...) \ 131 131 _CHECK(condition, tag, tattr.duration, format) 132 132 133 + #define ASSERT_EQ(actual, expected, name) ({ \ 134 + static int duration = 0; \ 135 + typeof(actual) ___act = (actual); \ 136 + typeof(expected) ___exp = (expected); \ 137 + bool ___ok = ___act == ___exp; \ 138 + CHECK(!___ok, (name), \ 139 + "unexpected %s: actual %lld != expected %lld\n", \ 140 + (name), (long long)(___act), (long long)(___exp)); \ 141 + ___ok; \ 142 + }) 143 + 144 + #define ASSERT_STREQ(actual, expected, name) ({ \ 145 + static int duration = 0; \ 146 + const char *___act = actual; \ 147 + const char *___exp = expected; \ 148 + bool ___ok = strcmp(___act, ___exp) == 0; \ 149 + CHECK(!___ok, (name), \ 150 + "unexpected %s: actual '%s' != expected '%s'\n", \ 151 + (name), ___act, ___exp); \ 152 + ___ok; \ 153 + }) 154 + 155 + #define ASSERT_OK(res, name) ({ \ 156 + static int duration = 0; \ 157 + long long ___res = (res); \ 158 + bool ___ok = ___res == 0; \ 159 + CHECK(!___ok, (name), "unexpected error: %lld\n", ___res); \ 160 + ___ok; \ 161 + }) 162 + 163 + #define ASSERT_ERR(res, name) ({ \ 164 + static int duration = 0; \ 165 + long long ___res = (res); \ 166 + bool ___ok = ___res < 0; \ 167 + CHECK(!___ok, (name), "unexpected success: %lld\n", ___res); \ 168 + ___ok; \ 169 + }) 170 + 171 + #define ASSERT_NULL(ptr, name) ({ \ 172 + static int duration = 0; \ 173 + const void *___res = (ptr); \ 174 + bool ___ok = !___res; \ 175 + CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res); \ 176 + ___ok; \ 177 + }) 178 + 179 + #define ASSERT_OK_PTR(ptr, name) ({ \ 180 + static int duration = 0; \ 181 + const void *___res = (ptr); \ 182 + bool ___ok = !IS_ERR_OR_NULL(___res); \ 183 + CHECK(!___ok, (name), \ 184 + "unexpected error: %ld\n", PTR_ERR(___res)); \ 185 + ___ok; \ 186 + }) 187 + 188 + #define ASSERT_ERR_PTR(ptr, name) ({ \ 189 + static int duration = 0; \ 190 + const void *___res = (ptr); \ 191 + bool ___ok = IS_ERR(___res) \ 192 + CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res); \ 193 + ___ok; \ 194 + }) 195 + 133 196 static inline __u64 ptr_to_u64(const void *ptr) 134 197 { 135 198 return (__u64) (unsigned long) ptr;