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

bpf: btf: Add BTF support to libbpf

If the ".BTF" elf section exists, libbpf will try to create
a btf_fd (through BPF_BTF_LOAD). If that fails, it will still
continue loading the bpf prog/map without the BTF.

If the bpf_object has a BTF loaded, it will create a map with the btf_fd.
libbpf will try to figure out the btf_key_id and btf_value_id of a map by
finding the BTF type with name "<map_name>_key" and "<map_name>_value".
If they cannot be found, it will continue without using the BTF.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Martin KaFai Lau and committed by
Daniel Borkmann
8a138aed 3bd86a84

+627 -32
+1 -1
tools/lib/bpf/Build
··· 1 - libbpf-y := libbpf.o bpf.o nlattr.o 1 + libbpf-y := libbpf.o bpf.o nlattr.o btf.o
+77 -19
tools/lib/bpf/bpf.c
··· 73 73 return syscall(__NR_bpf, cmd, attr, size); 74 74 } 75 75 76 - int bpf_create_map_node(enum bpf_map_type map_type, const char *name, 77 - int key_size, int value_size, int max_entries, 78 - __u32 map_flags, int node) 76 + int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr) 79 77 { 80 - __u32 name_len = name ? strlen(name) : 0; 78 + __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0; 81 79 union bpf_attr attr; 82 80 83 81 memset(&attr, '\0', sizeof(attr)); 84 82 85 - attr.map_type = map_type; 86 - attr.key_size = key_size; 87 - attr.value_size = value_size; 88 - attr.max_entries = max_entries; 89 - attr.map_flags = map_flags; 90 - memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); 91 - 92 - if (node >= 0) { 93 - attr.map_flags |= BPF_F_NUMA_NODE; 94 - attr.numa_node = node; 95 - } 83 + attr.map_type = create_attr->map_type; 84 + attr.key_size = create_attr->key_size; 85 + attr.value_size = create_attr->value_size; 86 + attr.max_entries = create_attr->max_entries; 87 + attr.map_flags = create_attr->map_flags; 88 + memcpy(attr.map_name, create_attr->name, 89 + min(name_len, BPF_OBJ_NAME_LEN - 1)); 90 + attr.numa_node = create_attr->numa_node; 91 + attr.btf_fd = create_attr->btf_fd; 92 + attr.btf_key_id = create_attr->btf_key_id; 93 + attr.btf_value_id = create_attr->btf_value_id; 96 94 97 95 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 96 + } 97 + 98 + int bpf_create_map_node(enum bpf_map_type map_type, const char *name, 99 + int key_size, int value_size, int max_entries, 100 + __u32 map_flags, int node) 101 + { 102 + struct bpf_create_map_attr map_attr = {}; 103 + 104 + map_attr.name = name; 105 + map_attr.map_type = map_type; 106 + map_attr.map_flags = map_flags; 107 + map_attr.key_size = key_size; 108 + map_attr.value_size = value_size; 109 + map_attr.max_entries = max_entries; 110 + if (node >= 0) { 111 + map_attr.numa_node = node; 112 + map_attr.map_flags |= BPF_F_NUMA_NODE; 113 + } 114 + 115 + return bpf_create_map_xattr(&map_attr); 98 116 } 99 117 100 118 int bpf_create_map(enum bpf_map_type map_type, int key_size, 101 119 int value_size, int max_entries, __u32 map_flags) 102 120 { 103 - return bpf_create_map_node(map_type, NULL, key_size, value_size, 104 - max_entries, map_flags, -1); 121 + struct bpf_create_map_attr map_attr = {}; 122 + 123 + map_attr.map_type = map_type; 124 + map_attr.map_flags = map_flags; 125 + map_attr.key_size = key_size; 126 + map_attr.value_size = value_size; 127 + map_attr.max_entries = max_entries; 128 + 129 + return bpf_create_map_xattr(&map_attr); 105 130 } 106 131 107 132 int bpf_create_map_name(enum bpf_map_type map_type, const char *name, 108 133 int key_size, int value_size, int max_entries, 109 134 __u32 map_flags) 110 135 { 111 - return bpf_create_map_node(map_type, name, key_size, value_size, 112 - max_entries, map_flags, -1); 136 + struct bpf_create_map_attr map_attr = {}; 137 + 138 + map_attr.name = name; 139 + map_attr.map_type = map_type; 140 + map_attr.map_flags = map_flags; 141 + map_attr.key_size = key_size; 142 + map_attr.value_size = value_size; 143 + map_attr.max_entries = max_entries; 144 + 145 + return bpf_create_map_xattr(&map_attr); 113 146 } 114 147 115 148 int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name, ··· 605 572 cleanup: 606 573 close(sock); 607 574 return ret; 575 + } 576 + 577 + int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, 578 + bool do_log) 579 + { 580 + union bpf_attr attr = {}; 581 + int fd; 582 + 583 + attr.btf = ptr_to_u64(btf); 584 + attr.btf_size = btf_size; 585 + 586 + retry: 587 + if (do_log && log_buf && log_buf_size) { 588 + attr.btf_log_level = 1; 589 + attr.btf_log_size = log_buf_size; 590 + attr.btf_log_buf = ptr_to_u64(log_buf); 591 + } 592 + 593 + fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr)); 594 + if (fd == -1 && !do_log && log_buf && log_buf_size) { 595 + do_log = true; 596 + goto retry; 597 + } 598 + 599 + return fd; 608 600 }
+16
tools/lib/bpf/bpf.h
··· 26 26 #include <linux/bpf.h> 27 27 #include <stddef.h> 28 28 29 + struct bpf_create_map_attr { 30 + const char *name; 31 + enum bpf_map_type map_type; 32 + __u32 map_flags; 33 + __u32 key_size; 34 + __u32 value_size; 35 + __u32 max_entries; 36 + __u32 numa_node; 37 + __u32 btf_fd; 38 + __u32 btf_key_id; 39 + __u32 btf_value_id; 40 + }; 41 + 42 + int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr); 29 43 int bpf_create_map_node(enum bpf_map_type map_type, const char *name, 30 44 int key_size, int value_size, int max_entries, 31 45 __u32 map_flags, int node); ··· 101 87 int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, 102 88 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt); 103 89 int bpf_raw_tracepoint_open(const char *name, int prog_fd); 90 + int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, 91 + bool do_log); 104 92 #endif
+374
tools/lib/bpf/btf.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2018 Facebook */ 3 + 4 + #include <stdlib.h> 5 + #include <stdint.h> 6 + #include <string.h> 7 + #include <unistd.h> 8 + #include <errno.h> 9 + #include <linux/err.h> 10 + #include <linux/btf.h> 11 + #include "btf.h" 12 + #include "bpf.h" 13 + 14 + #define elog(fmt, ...) { if (err_log) err_log(fmt, ##__VA_ARGS__); } 15 + #define max(a, b) ((a) > (b) ? (a) : (b)) 16 + #define min(a, b) ((a) < (b) ? (a) : (b)) 17 + 18 + #define BTF_MAX_NR_TYPES 65535 19 + 20 + static struct btf_type btf_void; 21 + 22 + struct btf { 23 + union { 24 + struct btf_header *hdr; 25 + void *data; 26 + }; 27 + struct btf_type **types; 28 + const char *strings; 29 + void *nohdr_data; 30 + uint32_t nr_types; 31 + uint32_t types_size; 32 + uint32_t data_size; 33 + int fd; 34 + }; 35 + 36 + static const char *btf_name_by_offset(const struct btf *btf, uint32_t offset) 37 + { 38 + if (!BTF_STR_TBL_ELF_ID(offset) && 39 + BTF_STR_OFFSET(offset) < btf->hdr->str_len) 40 + return &btf->strings[BTF_STR_OFFSET(offset)]; 41 + else 42 + return NULL; 43 + } 44 + 45 + static int btf_add_type(struct btf *btf, struct btf_type *t) 46 + { 47 + if (btf->types_size - btf->nr_types < 2) { 48 + struct btf_type **new_types; 49 + u32 expand_by, new_size; 50 + 51 + if (btf->types_size == BTF_MAX_NR_TYPES) 52 + return -E2BIG; 53 + 54 + expand_by = max(btf->types_size >> 2, 16); 55 + new_size = min(BTF_MAX_NR_TYPES, btf->types_size + expand_by); 56 + 57 + new_types = realloc(btf->types, sizeof(*new_types) * new_size); 58 + if (!new_types) 59 + return -ENOMEM; 60 + 61 + if (btf->nr_types == 0) 62 + new_types[0] = &btf_void; 63 + 64 + btf->types = new_types; 65 + btf->types_size = new_size; 66 + } 67 + 68 + btf->types[++(btf->nr_types)] = t; 69 + 70 + return 0; 71 + } 72 + 73 + static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log) 74 + { 75 + const struct btf_header *hdr = btf->hdr; 76 + u32 meta_left; 77 + 78 + if (btf->data_size < sizeof(struct btf_header)) { 79 + elog("BTF header not found\n"); 80 + return -EINVAL; 81 + } 82 + 83 + if (hdr->magic != BTF_MAGIC) { 84 + elog("Invalid BTF magic:%x\n", hdr->magic); 85 + return -EINVAL; 86 + } 87 + 88 + if (hdr->version != BTF_VERSION) { 89 + elog("Unsupported BTF version:%u\n", hdr->version); 90 + return -ENOTSUP; 91 + } 92 + 93 + if (hdr->flags) { 94 + elog("Unsupported BTF flags:%x\n", hdr->flags); 95 + return -ENOTSUP; 96 + } 97 + 98 + meta_left = btf->data_size - sizeof(*hdr); 99 + if (!meta_left) { 100 + elog("BTF has no data\n"); 101 + return -EINVAL; 102 + } 103 + 104 + if (meta_left < hdr->type_off) { 105 + elog("Invalid BTF type section offset:%u\n", hdr->type_off); 106 + return -EINVAL; 107 + } 108 + 109 + if (meta_left < hdr->str_off) { 110 + elog("Invalid BTF string section offset:%u\n", hdr->str_off); 111 + return -EINVAL; 112 + } 113 + 114 + if (hdr->type_off >= hdr->str_off) { 115 + elog("BTF type section offset >= string section offset. No type?\n"); 116 + return -EINVAL; 117 + } 118 + 119 + if (hdr->type_off & 0x02) { 120 + elog("BTF type section is not aligned to 4 bytes\n"); 121 + return -EINVAL; 122 + } 123 + 124 + btf->nohdr_data = btf->hdr + 1; 125 + 126 + return 0; 127 + } 128 + 129 + static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log) 130 + { 131 + const struct btf_header *hdr = btf->hdr; 132 + const char *start = btf->nohdr_data + hdr->str_off; 133 + const char *end = start + btf->hdr->str_len; 134 + 135 + if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_NAME_OFFSET || 136 + start[0] || end[-1]) { 137 + elog("Invalid BTF string section\n"); 138 + return -EINVAL; 139 + } 140 + 141 + btf->strings = start; 142 + 143 + return 0; 144 + } 145 + 146 + static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log) 147 + { 148 + struct btf_header *hdr = btf->hdr; 149 + void *nohdr_data = btf->nohdr_data; 150 + void *next_type = nohdr_data + hdr->type_off; 151 + void *end_type = nohdr_data + hdr->str_off; 152 + 153 + while (next_type < end_type) { 154 + struct btf_type *t = next_type; 155 + uint16_t vlen = BTF_INFO_VLEN(t->info); 156 + int err; 157 + 158 + next_type += sizeof(*t); 159 + switch (BTF_INFO_KIND(t->info)) { 160 + case BTF_KIND_INT: 161 + next_type += sizeof(int); 162 + break; 163 + case BTF_KIND_ARRAY: 164 + next_type += sizeof(struct btf_array); 165 + break; 166 + case BTF_KIND_STRUCT: 167 + case BTF_KIND_UNION: 168 + next_type += vlen * sizeof(struct btf_member); 169 + break; 170 + case BTF_KIND_ENUM: 171 + next_type += vlen * sizeof(struct btf_enum); 172 + break; 173 + case BTF_KIND_TYPEDEF: 174 + case BTF_KIND_PTR: 175 + case BTF_KIND_FWD: 176 + case BTF_KIND_VOLATILE: 177 + case BTF_KIND_CONST: 178 + case BTF_KIND_RESTRICT: 179 + break; 180 + default: 181 + elog("Unsupported BTF_KIND:%u\n", 182 + BTF_INFO_KIND(t->info)); 183 + return -EINVAL; 184 + } 185 + 186 + err = btf_add_type(btf, t); 187 + if (err) 188 + return err; 189 + } 190 + 191 + return 0; 192 + } 193 + 194 + static const struct btf_type *btf_type_by_id(const struct btf *btf, 195 + uint32_t type_id) 196 + { 197 + if (type_id > btf->nr_types) 198 + return NULL; 199 + 200 + return btf->types[type_id]; 201 + } 202 + 203 + static bool btf_type_is_void(const struct btf_type *t) 204 + { 205 + return t == &btf_void || BTF_INFO_KIND(t->info) == BTF_KIND_FWD; 206 + } 207 + 208 + static bool btf_type_is_void_or_null(const struct btf_type *t) 209 + { 210 + return !t || btf_type_is_void(t); 211 + } 212 + 213 + static int64_t btf_type_size(const struct btf_type *t) 214 + { 215 + switch (BTF_INFO_KIND(t->info)) { 216 + case BTF_KIND_INT: 217 + case BTF_KIND_STRUCT: 218 + case BTF_KIND_UNION: 219 + case BTF_KIND_ENUM: 220 + return t->size; 221 + case BTF_KIND_PTR: 222 + return sizeof(void *); 223 + default: 224 + return -EINVAL; 225 + } 226 + } 227 + 228 + #define MAX_RESOLVE_DEPTH 32 229 + 230 + int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) 231 + { 232 + const struct btf_array *array; 233 + const struct btf_type *t; 234 + uint32_t nelems = 1; 235 + int64_t size = -1; 236 + int i; 237 + 238 + t = btf_type_by_id(btf, type_id); 239 + for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t); 240 + i++) { 241 + size = btf_type_size(t); 242 + if (size >= 0) 243 + break; 244 + 245 + switch (BTF_INFO_KIND(t->info)) { 246 + case BTF_KIND_TYPEDEF: 247 + case BTF_KIND_VOLATILE: 248 + case BTF_KIND_CONST: 249 + case BTF_KIND_RESTRICT: 250 + type_id = t->type; 251 + break; 252 + case BTF_KIND_ARRAY: 253 + array = (const struct btf_array *)(t + 1); 254 + if (nelems && array->nelems > UINT32_MAX / nelems) 255 + return -E2BIG; 256 + nelems *= array->nelems; 257 + type_id = array->type; 258 + break; 259 + default: 260 + return -EINVAL; 261 + } 262 + 263 + t = btf_type_by_id(btf, type_id); 264 + } 265 + 266 + if (size < 0) 267 + return -EINVAL; 268 + 269 + if (nelems && size > UINT32_MAX / nelems) 270 + return -E2BIG; 271 + 272 + return nelems * size; 273 + } 274 + 275 + int32_t btf__find_by_name(const struct btf *btf, const char *type_name) 276 + { 277 + uint32_t i; 278 + 279 + if (!strcmp(type_name, "void")) 280 + return 0; 281 + 282 + for (i = 1; i <= btf->nr_types; i++) { 283 + const struct btf_type *t = btf->types[i]; 284 + const char *name = btf_name_by_offset(btf, t->name); 285 + 286 + if (name && !strcmp(type_name, name)) 287 + return i; 288 + } 289 + 290 + return -ENOENT; 291 + } 292 + 293 + void btf__free(struct btf *btf) 294 + { 295 + if (!btf) 296 + return; 297 + 298 + if (btf->fd != -1) 299 + close(btf->fd); 300 + 301 + free(btf->data); 302 + free(btf->types); 303 + free(btf); 304 + } 305 + 306 + struct btf *btf__new(uint8_t *data, uint32_t size, 307 + btf_print_fn_t err_log) 308 + { 309 + uint32_t log_buf_size = 0; 310 + char *log_buf = NULL; 311 + struct btf *btf; 312 + int err; 313 + 314 + btf = calloc(1, sizeof(struct btf)); 315 + if (!btf) 316 + return ERR_PTR(-ENOMEM); 317 + 318 + btf->fd = -1; 319 + 320 + if (err_log) { 321 + log_buf = malloc(BPF_LOG_BUF_SIZE); 322 + if (!log_buf) { 323 + err = -ENOMEM; 324 + goto done; 325 + } 326 + *log_buf = 0; 327 + log_buf_size = BPF_LOG_BUF_SIZE; 328 + } 329 + 330 + btf->data = malloc(size); 331 + if (!btf->data) { 332 + err = -ENOMEM; 333 + goto done; 334 + } 335 + 336 + memcpy(btf->data, data, size); 337 + btf->data_size = size; 338 + 339 + btf->fd = bpf_load_btf(btf->data, btf->data_size, 340 + log_buf, log_buf_size, false); 341 + 342 + if (btf->fd == -1) { 343 + err = -errno; 344 + elog("Error loading BTF: %s(%d)\n", strerror(errno), errno); 345 + if (log_buf && *log_buf) 346 + elog("%s\n", log_buf); 347 + goto done; 348 + } 349 + 350 + err = btf_parse_hdr(btf, err_log); 351 + if (err) 352 + goto done; 353 + 354 + err = btf_parse_str_sec(btf, err_log); 355 + if (err) 356 + goto done; 357 + 358 + err = btf_parse_type_sec(btf, err_log); 359 + 360 + done: 361 + free(log_buf); 362 + 363 + if (err) { 364 + btf__free(btf); 365 + return ERR_PTR(err); 366 + } 367 + 368 + return btf; 369 + } 370 + 371 + int btf__fd(const struct btf *btf) 372 + { 373 + return btf->fd; 374 + }
+22
tools/lib/bpf/btf.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2018 Facebook */ 3 + 4 + #ifndef __BPF_BTF_H 5 + #define __BPF_BTF_H 6 + 7 + #include <stdint.h> 8 + 9 + #define BTF_ELF_SEC ".BTF" 10 + 11 + struct btf; 12 + 13 + typedef int (*btf_print_fn_t)(const char *, ...) 14 + __attribute__((format(printf, 1, 2))); 15 + 16 + void btf__free(struct btf *btf); 17 + struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log); 18 + int32_t btf__find_by_name(const struct btf *btf, const char *type_name); 19 + int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id); 20 + int btf__fd(const struct btf *btf); 21 + 22 + #endif
+134 -12
tools/lib/bpf/libbpf.c
··· 45 45 46 46 #include "libbpf.h" 47 47 #include "bpf.h" 48 + #include "btf.h" 48 49 49 50 #ifndef EM_BPF 50 51 #define EM_BPF 247 ··· 213 212 char *name; 214 213 size_t offset; 215 214 struct bpf_map_def def; 215 + uint32_t btf_key_id; 216 + uint32_t btf_value_id; 216 217 void *priv; 217 218 bpf_map_clear_priv_t clear_priv; 218 219 }; ··· 258 255 * all objects. 259 256 */ 260 257 struct list_head list; 258 + 259 + struct btf *btf; 261 260 262 261 void *priv; 263 262 bpf_object_clear_priv_t clear_priv; ··· 824 819 data->d_size); 825 820 else if (strcmp(name, "maps") == 0) 826 821 obj->efile.maps_shndx = idx; 827 - else if (sh.sh_type == SHT_SYMTAB) { 822 + else if (strcmp(name, BTF_ELF_SEC) == 0) { 823 + obj->btf = btf__new(data->d_buf, data->d_size, 824 + __pr_debug); 825 + if (IS_ERR(obj->btf)) { 826 + pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", 827 + BTF_ELF_SEC, PTR_ERR(obj->btf)); 828 + obj->btf = NULL; 829 + } 830 + } else if (sh.sh_type == SHT_SYMTAB) { 828 831 if (obj->efile.symbols) { 829 832 pr_warning("bpf: multiple SYMTAB in %s\n", 830 833 obj->path); ··· 1009 996 return 0; 1010 997 } 1011 998 999 + static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) 1000 + { 1001 + struct bpf_map_def *def = &map->def; 1002 + const size_t max_name = 256; 1003 + int64_t key_size, value_size; 1004 + int32_t key_id, value_id; 1005 + char name[max_name]; 1006 + 1007 + /* Find key type by name from BTF */ 1008 + if (snprintf(name, max_name, "%s_key", map->name) == max_name) { 1009 + pr_warning("map:%s length of BTF key_type:%s_key is too long\n", 1010 + map->name, map->name); 1011 + return -EINVAL; 1012 + } 1013 + 1014 + key_id = btf__find_by_name(btf, name); 1015 + if (key_id < 0) { 1016 + pr_debug("map:%s key_type:%s cannot be found in BTF\n", 1017 + map->name, name); 1018 + return key_id; 1019 + } 1020 + 1021 + key_size = btf__resolve_size(btf, key_id); 1022 + if (key_size < 0) { 1023 + pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", 1024 + map->name, name); 1025 + return key_size; 1026 + } 1027 + 1028 + if (def->key_size != key_size) { 1029 + pr_warning("map:%s key_type:%s has BTF type_size:%ld != key_size:%u\n", 1030 + map->name, name, key_size, def->key_size); 1031 + return -EINVAL; 1032 + } 1033 + 1034 + /* Find value type from BTF */ 1035 + if (snprintf(name, max_name, "%s_value", map->name) == max_name) { 1036 + pr_warning("map:%s length of BTF value_type:%s_value is too long\n", 1037 + map->name, map->name); 1038 + return -EINVAL; 1039 + } 1040 + 1041 + value_id = btf__find_by_name(btf, name); 1042 + if (value_id < 0) { 1043 + pr_debug("map:%s value_type:%s cannot be found in BTF\n", 1044 + map->name, name); 1045 + return value_id; 1046 + } 1047 + 1048 + value_size = btf__resolve_size(btf, value_id); 1049 + if (value_size < 0) { 1050 + pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", 1051 + map->name, name); 1052 + return value_size; 1053 + } 1054 + 1055 + if (def->value_size != value_size) { 1056 + pr_warning("map:%s value_type:%s has BTF type_size:%ld != value_size:%u\n", 1057 + map->name, name, value_size, def->value_size); 1058 + return -EINVAL; 1059 + } 1060 + 1061 + map->btf_key_id = key_id; 1062 + map->btf_value_id = value_id; 1063 + 1064 + return 0; 1065 + } 1066 + 1012 1067 static int 1013 1068 bpf_object__create_maps(struct bpf_object *obj) 1014 1069 { 1070 + struct bpf_create_map_attr create_attr = {}; 1015 1071 unsigned int i; 1072 + int err; 1016 1073 1017 1074 for (i = 0; i < obj->nr_maps; i++) { 1018 - struct bpf_map_def *def = &obj->maps[i].def; 1019 - int *pfd = &obj->maps[i].fd; 1075 + struct bpf_map *map = &obj->maps[i]; 1076 + struct bpf_map_def *def = &map->def; 1077 + int *pfd = &map->fd; 1020 1078 1021 - *pfd = bpf_create_map_name(def->type, 1022 - obj->maps[i].name, 1023 - def->key_size, 1024 - def->value_size, 1025 - def->max_entries, 1026 - def->map_flags); 1079 + create_attr.name = map->name; 1080 + create_attr.map_type = def->type; 1081 + create_attr.map_flags = def->map_flags; 1082 + create_attr.key_size = def->key_size; 1083 + create_attr.value_size = def->value_size; 1084 + create_attr.max_entries = def->max_entries; 1085 + create_attr.btf_fd = 0; 1086 + create_attr.btf_key_id = 0; 1087 + create_attr.btf_value_id = 0; 1088 + 1089 + if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) { 1090 + create_attr.btf_fd = btf__fd(obj->btf); 1091 + create_attr.btf_key_id = map->btf_key_id; 1092 + create_attr.btf_value_id = map->btf_value_id; 1093 + } 1094 + 1095 + *pfd = bpf_create_map_xattr(&create_attr); 1096 + if (*pfd < 0 && create_attr.btf_key_id) { 1097 + pr_warning("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n", 1098 + map->name, strerror(errno), errno); 1099 + create_attr.btf_fd = 0; 1100 + create_attr.btf_key_id = 0; 1101 + create_attr.btf_value_id = 0; 1102 + map->btf_key_id = 0; 1103 + map->btf_value_id = 0; 1104 + *pfd = bpf_create_map_xattr(&create_attr); 1105 + } 1106 + 1027 1107 if (*pfd < 0) { 1028 1108 size_t j; 1029 - int err = *pfd; 1030 1109 1110 + err = *pfd; 1031 1111 pr_warning("failed to create map (name: '%s'): %s\n", 1032 - obj->maps[i].name, 1112 + map->name, 1033 1113 strerror(errno)); 1034 1114 for (j = 0; j < i; j++) 1035 1115 zclose(obj->maps[j].fd); 1036 1116 return err; 1037 1117 } 1038 - pr_debug("create map %s: fd=%d\n", obj->maps[i].name, *pfd); 1118 + pr_debug("create map %s: fd=%d\n", map->name, *pfd); 1039 1119 } 1040 1120 1041 1121 return 0; ··· 1747 1641 1748 1642 bpf_object__elf_finish(obj); 1749 1643 bpf_object__unload(obj); 1644 + btf__free(obj->btf); 1750 1645 1751 1646 for (i = 0; i < obj->nr_maps; i++) { 1752 1647 zfree(&obj->maps[i].name); ··· 1797 1690 unsigned int bpf_object__kversion(struct bpf_object *obj) 1798 1691 { 1799 1692 return obj ? obj->kern_version : 0; 1693 + } 1694 + 1695 + int bpf_object__btf_fd(const struct bpf_object *obj) 1696 + { 1697 + return obj->btf ? btf__fd(obj->btf) : -1; 1800 1698 } 1801 1699 1802 1700 int bpf_object__set_priv(struct bpf_object *obj, void *priv, ··· 2047 1935 const char *bpf_map__name(struct bpf_map *map) 2048 1936 { 2049 1937 return map ? map->name : NULL; 1938 + } 1939 + 1940 + uint32_t bpf_map__btf_key_id(const struct bpf_map *map) 1941 + { 1942 + return map ? map->btf_key_id : 0; 1943 + } 1944 + 1945 + uint32_t bpf_map__btf_value_id(const struct bpf_map *map) 1946 + { 1947 + return map ? map->btf_value_id : 0; 2050 1948 } 2051 1949 2052 1950 int bpf_map__set_priv(struct bpf_map *map, void *priv,
+3
tools/lib/bpf/libbpf.h
··· 78 78 int bpf_object__unload(struct bpf_object *obj); 79 79 const char *bpf_object__name(struct bpf_object *obj); 80 80 unsigned int bpf_object__kversion(struct bpf_object *obj); 81 + int bpf_object__btf_fd(const struct bpf_object *obj); 81 82 82 83 struct bpf_object *bpf_object__next(struct bpf_object *prev); 83 84 #define bpf_object__for_each_safe(pos, tmp) \ ··· 242 241 int bpf_map__fd(struct bpf_map *map); 243 242 const struct bpf_map_def *bpf_map__def(struct bpf_map *map); 244 243 const char *bpf_map__name(struct bpf_map *map); 244 + uint32_t bpf_map__btf_key_id(const struct bpf_map *map); 245 + uint32_t bpf_map__btf_value_id(const struct bpf_map *map); 245 246 246 247 typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); 247 248 int bpf_map__set_priv(struct bpf_map *map, void *priv,