aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/Build2
-rw-r--r--tools/lib/bpf/bpf.c92
-rw-r--r--tools/lib/bpf/bpf.h16
-rw-r--r--tools/lib/bpf/btf.c374
-rw-r--r--tools/lib/bpf/btf.h22
-rw-r--r--tools/lib/bpf/libbpf.c148
-rw-r--r--tools/lib/bpf/libbpf.h3
7 files changed, 626 insertions, 31 deletions
diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index 64c679d67109..6070e655042d 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1 @@
libbpf-y := libbpf.o bpf.o nlattr.o libbpf-y := libbpf.o bpf.o nlattr.o btf.o
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index acbb3f8b3bec..76b36cc16e7f 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -73,43 +73,76 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
73 return syscall(__NR_bpf, cmd, attr, size); 73 return syscall(__NR_bpf, cmd, attr, size);
74} 74}
75 75
76int bpf_create_map_node(enum bpf_map_type map_type, const char *name, 76int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
77 int key_size, int value_size, int max_entries,
78 __u32 map_flags, int node)
79{ 77{
80 __u32 name_len = name ? strlen(name) : 0; 78 __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0;
81 union bpf_attr attr; 79 union bpf_attr attr;
82 80
83 memset(&attr, '\0', sizeof(attr)); 81 memset(&attr, '\0', sizeof(attr));
84 82
85 attr.map_type = map_type; 83 attr.map_type = create_attr->map_type;
86 attr.key_size = key_size; 84 attr.key_size = create_attr->key_size;
87 attr.value_size = value_size; 85 attr.value_size = create_attr->value_size;
88 attr.max_entries = max_entries; 86 attr.max_entries = create_attr->max_entries;
89 attr.map_flags = map_flags; 87 attr.map_flags = create_attr->map_flags;
90 memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); 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;
94
95 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
96}
91 97
98int 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;
92 if (node >= 0) { 110 if (node >= 0) {
93 attr.map_flags |= BPF_F_NUMA_NODE; 111 map_attr.numa_node = node;
94 attr.numa_node = node; 112 map_attr.map_flags |= BPF_F_NUMA_NODE;
95 } 113 }
96 114
97 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 115 return bpf_create_map_xattr(&map_attr);
98} 116}
99 117
100int bpf_create_map(enum bpf_map_type map_type, int key_size, 118int bpf_create_map(enum bpf_map_type map_type, int key_size,
101 int value_size, int max_entries, __u32 map_flags) 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, 121 struct bpf_create_map_attr map_attr = {};
104 max_entries, map_flags, -1); 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
107int bpf_create_map_name(enum bpf_map_type map_type, const char *name, 132int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
108 int key_size, int value_size, int max_entries, 133 int key_size, int value_size, int max_entries,
109 __u32 map_flags) 134 __u32 map_flags)
110{ 135{
111 return bpf_create_map_node(map_type, name, key_size, value_size, 136 struct bpf_create_map_attr map_attr = {};
112 max_entries, map_flags, -1); 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
115int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name, 148int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
@@ -573,3 +606,28 @@ cleanup:
573 close(sock); 606 close(sock);
574 return ret; 607 return ret;
575} 608}
609
610int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
611 bool do_log)
612{
613 union bpf_attr attr = {};
614 int fd;
615
616 attr.btf = ptr_to_u64(btf);
617 attr.btf_size = btf_size;
618
619retry:
620 if (do_log && log_buf && log_buf_size) {
621 attr.btf_log_level = 1;
622 attr.btf_log_size = log_buf_size;
623 attr.btf_log_buf = ptr_to_u64(log_buf);
624 }
625
626 fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr));
627 if (fd == -1 && !do_log && log_buf && log_buf_size) {
628 do_log = true;
629 goto retry;
630 }
631
632 return fd;
633}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 39f6a0d64a3b..01bda076310f 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -26,6 +26,20 @@
26#include <linux/bpf.h> 26#include <linux/bpf.h>
27#include <stddef.h> 27#include <stddef.h>
28 28
29struct 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
42int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr);
29int bpf_create_map_node(enum bpf_map_type map_type, const char *name, 43int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
30 int key_size, int value_size, int max_entries, 44 int key_size, int value_size, int max_entries,
31 __u32 map_flags, int node); 45 __u32 map_flags, int node);
@@ -87,4 +101,6 @@ int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len);
87int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, 101int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
88 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt); 102 __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt);
89int bpf_raw_tracepoint_open(const char *name, int prog_fd); 103int bpf_raw_tracepoint_open(const char *name, int prog_fd);
104int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
105 bool do_log);
90#endif 106#endif
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
new file mode 100644
index 000000000000..58b6255abc7a
--- /dev/null
+++ b/tools/lib/bpf/btf.c
@@ -0,0 +1,374 @@
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
20static struct btf_type btf_void;
21
22struct 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
36static 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
45static 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
73static 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
129static 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
146static 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
194static 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
203static 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
208static bool btf_type_is_void_or_null(const struct btf_type *t)
209{
210 return !t || btf_type_is_void(t);
211}
212
213static 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
230int64_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
275int32_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
293void 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
306struct 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
360done:
361 free(log_buf);
362
363 if (err) {
364 btf__free(btf);
365 return ERR_PTR(err);
366 }
367
368 return btf;
369}
370
371int btf__fd(const struct btf *btf)
372{
373 return btf->fd;
374}
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
new file mode 100644
index 000000000000..74bb344035bb
--- /dev/null
+++ b/tools/lib/bpf/btf.h
@@ -0,0 +1,22 @@
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
11struct btf;
12
13typedef int (*btf_print_fn_t)(const char *, ...)
14 __attribute__((format(printf, 1, 2)));
15
16void btf__free(struct btf *btf);
17struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log);
18int32_t btf__find_by_name(const struct btf *btf, const char *type_name);
19int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id);
20int btf__fd(const struct btf *btf);
21
22#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 3d35bacf656f..6513e0b08795 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -45,6 +45,7 @@
45 45
46#include "libbpf.h" 46#include "libbpf.h"
47#include "bpf.h" 47#include "bpf.h"
48#include "btf.h"
48 49
49#ifndef EM_BPF 50#ifndef EM_BPF
50#define EM_BPF 247 51#define EM_BPF 247
@@ -212,6 +213,8 @@ struct bpf_map {
212 char *name; 213 char *name;
213 size_t offset; 214 size_t offset;
214 struct bpf_map_def def; 215 struct bpf_map_def def;
216 uint32_t btf_key_id;
217 uint32_t btf_value_id;
215 void *priv; 218 void *priv;
216 bpf_map_clear_priv_t clear_priv; 219 bpf_map_clear_priv_t clear_priv;
217}; 220};
@@ -256,6 +259,8 @@ struct bpf_object {
256 */ 259 */
257 struct list_head list; 260 struct list_head list;
258 261
262 struct btf *btf;
263
259 void *priv; 264 void *priv;
260 bpf_object_clear_priv_t clear_priv; 265 bpf_object_clear_priv_t clear_priv;
261 266
@@ -819,7 +824,15 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
819 data->d_size); 824 data->d_size);
820 else if (strcmp(name, "maps") == 0) 825 else if (strcmp(name, "maps") == 0)
821 obj->efile.maps_shndx = idx; 826 obj->efile.maps_shndx = idx;
822 else if (sh.sh_type == SHT_SYMTAB) { 827 else if (strcmp(name, BTF_ELF_SEC) == 0) {
828 obj->btf = btf__new(data->d_buf, data->d_size,
829 __pr_debug);
830 if (IS_ERR(obj->btf)) {
831 pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
832 BTF_ELF_SEC, PTR_ERR(obj->btf));
833 obj->btf = NULL;
834 }
835 } else if (sh.sh_type == SHT_SYMTAB) {
823 if (obj->efile.symbols) { 836 if (obj->efile.symbols) {
824 pr_warning("bpf: multiple SYMTAB in %s\n", 837 pr_warning("bpf: multiple SYMTAB in %s\n",
825 obj->path); 838 obj->path);
@@ -996,33 +1009,126 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
996 return 0; 1009 return 0;
997} 1010}
998 1011
1012static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
1013{
1014 struct bpf_map_def *def = &map->def;
1015 const size_t max_name = 256;
1016 int64_t key_size, value_size;
1017 int32_t key_id, value_id;
1018 char name[max_name];
1019
1020 /* Find key type by name from BTF */
1021 if (snprintf(name, max_name, "%s_key", map->name) == max_name) {
1022 pr_warning("map:%s length of BTF key_type:%s_key is too long\n",
1023 map->name, map->name);
1024 return -EINVAL;
1025 }
1026
1027 key_id = btf__find_by_name(btf, name);
1028 if (key_id < 0) {
1029 pr_debug("map:%s key_type:%s cannot be found in BTF\n",
1030 map->name, name);
1031 return key_id;
1032 }
1033
1034 key_size = btf__resolve_size(btf, key_id);
1035 if (key_size < 0) {
1036 pr_warning("map:%s key_type:%s cannot get the BTF type_size\n",
1037 map->name, name);
1038 return key_size;
1039 }
1040
1041 if (def->key_size != key_size) {
1042 pr_warning("map:%s key_type:%s has BTF type_size:%ld != key_size:%u\n",
1043 map->name, name, key_size, def->key_size);
1044 return -EINVAL;
1045 }
1046
1047 /* Find value type from BTF */
1048 if (snprintf(name, max_name, "%s_value", map->name) == max_name) {
1049 pr_warning("map:%s length of BTF value_type:%s_value is too long\n",
1050 map->name, map->name);
1051 return -EINVAL;
1052 }
1053
1054 value_id = btf__find_by_name(btf, name);
1055 if (value_id < 0) {
1056 pr_debug("map:%s value_type:%s cannot be found in BTF\n",
1057 map->name, name);
1058 return value_id;
1059 }
1060
1061 value_size = btf__resolve_size(btf, value_id);
1062 if (value_size < 0) {
1063 pr_warning("map:%s value_type:%s cannot get the BTF type_size\n",
1064 map->name, name);
1065 return value_size;
1066 }
1067
1068 if (def->value_size != value_size) {
1069 pr_warning("map:%s value_type:%s has BTF type_size:%ld != value_size:%u\n",
1070 map->name, name, value_size, def->value_size);
1071 return -EINVAL;
1072 }
1073
1074 map->btf_key_id = key_id;
1075 map->btf_value_id = value_id;
1076
1077 return 0;
1078}
1079
999static int 1080static int
1000bpf_object__create_maps(struct bpf_object *obj) 1081bpf_object__create_maps(struct bpf_object *obj)
1001{ 1082{
1083 struct bpf_create_map_attr create_attr = {};
1002 unsigned int i; 1084 unsigned int i;
1085 int err;
1003 1086
1004 for (i = 0; i < obj->nr_maps; i++) { 1087 for (i = 0; i < obj->nr_maps; i++) {
1005 struct bpf_map_def *def = &obj->maps[i].def; 1088 struct bpf_map *map = &obj->maps[i];
1006 int *pfd = &obj->maps[i].fd; 1089 struct bpf_map_def *def = &map->def;
1007 1090 int *pfd = &map->fd;
1008 *pfd = bpf_create_map_name(def->type, 1091
1009 obj->maps[i].name, 1092 create_attr.name = map->name;
1010 def->key_size, 1093 create_attr.map_type = def->type;
1011 def->value_size, 1094 create_attr.map_flags = def->map_flags;
1012 def->max_entries, 1095 create_attr.key_size = def->key_size;
1013 def->map_flags); 1096 create_attr.value_size = def->value_size;
1097 create_attr.max_entries = def->max_entries;
1098 create_attr.btf_fd = 0;
1099 create_attr.btf_key_id = 0;
1100 create_attr.btf_value_id = 0;
1101
1102 if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) {
1103 create_attr.btf_fd = btf__fd(obj->btf);
1104 create_attr.btf_key_id = map->btf_key_id;
1105 create_attr.btf_value_id = map->btf_value_id;
1106 }
1107
1108 *pfd = bpf_create_map_xattr(&create_attr);
1109 if (*pfd < 0 && create_attr.btf_key_id) {
1110 pr_warning("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n",
1111 map->name, strerror(errno), errno);
1112 create_attr.btf_fd = 0;
1113 create_attr.btf_key_id = 0;
1114 create_attr.btf_value_id = 0;
1115 map->btf_key_id = 0;
1116 map->btf_value_id = 0;
1117 *pfd = bpf_create_map_xattr(&create_attr);
1118 }
1119
1014 if (*pfd < 0) { 1120 if (*pfd < 0) {
1015 size_t j; 1121 size_t j;
1016 int err = *pfd;
1017 1122
1123 err = *pfd;
1018 pr_warning("failed to create map (name: '%s'): %s\n", 1124 pr_warning("failed to create map (name: '%s'): %s\n",
1019 obj->maps[i].name, 1125 map->name,
1020 strerror(errno)); 1126 strerror(errno));
1021 for (j = 0; j < i; j++) 1127 for (j = 0; j < i; j++)
1022 zclose(obj->maps[j].fd); 1128 zclose(obj->maps[j].fd);
1023 return err; 1129 return err;
1024 } 1130 }
1025 pr_debug("create map %s: fd=%d\n", obj->maps[i].name, *pfd); 1131 pr_debug("create map %s: fd=%d\n", map->name, *pfd);
1026 } 1132 }
1027 1133
1028 return 0; 1134 return 0;
@@ -1641,6 +1747,7 @@ void bpf_object__close(struct bpf_object *obj)
1641 1747
1642 bpf_object__elf_finish(obj); 1748 bpf_object__elf_finish(obj);
1643 bpf_object__unload(obj); 1749 bpf_object__unload(obj);
1750 btf__free(obj->btf);
1644 1751
1645 for (i = 0; i < obj->nr_maps; i++) { 1752 for (i = 0; i < obj->nr_maps; i++) {
1646 zfree(&obj->maps[i].name); 1753 zfree(&obj->maps[i].name);
@@ -1692,6 +1799,11 @@ unsigned int bpf_object__kversion(struct bpf_object *obj)
1692 return obj ? obj->kern_version : 0; 1799 return obj ? obj->kern_version : 0;
1693} 1800}
1694 1801
1802int bpf_object__btf_fd(const struct bpf_object *obj)
1803{
1804 return obj->btf ? btf__fd(obj->btf) : -1;
1805}
1806
1695int bpf_object__set_priv(struct bpf_object *obj, void *priv, 1807int bpf_object__set_priv(struct bpf_object *obj, void *priv,
1696 bpf_object_clear_priv_t clear_priv) 1808 bpf_object_clear_priv_t clear_priv)
1697{ 1809{
@@ -1937,6 +2049,16 @@ const char *bpf_map__name(struct bpf_map *map)
1937 return map ? map->name : NULL; 2049 return map ? map->name : NULL;
1938} 2050}
1939 2051
2052uint32_t bpf_map__btf_key_id(const struct bpf_map *map)
2053{
2054 return map ? map->btf_key_id : 0;
2055}
2056
2057uint32_t bpf_map__btf_value_id(const struct bpf_map *map)
2058{
2059 return map ? map->btf_value_id : 0;
2060}
2061
1940int bpf_map__set_priv(struct bpf_map *map, void *priv, 2062int bpf_map__set_priv(struct bpf_map *map, void *priv,
1941 bpf_map_clear_priv_t clear_priv) 2063 bpf_map_clear_priv_t clear_priv)
1942{ 2064{
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 8b242486b464..d6ac4fa6f472 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -78,6 +78,7 @@ int bpf_object__load(struct bpf_object *obj);
78int bpf_object__unload(struct bpf_object *obj); 78int bpf_object__unload(struct bpf_object *obj);
79const char *bpf_object__name(struct bpf_object *obj); 79const char *bpf_object__name(struct bpf_object *obj);
80unsigned int bpf_object__kversion(struct bpf_object *obj); 80unsigned int bpf_object__kversion(struct bpf_object *obj);
81int bpf_object__btf_fd(const struct bpf_object *obj);
81 82
82struct bpf_object *bpf_object__next(struct bpf_object *prev); 83struct bpf_object *bpf_object__next(struct bpf_object *prev);
83#define bpf_object__for_each_safe(pos, tmp) \ 84#define bpf_object__for_each_safe(pos, tmp) \
@@ -241,6 +242,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
241int bpf_map__fd(struct bpf_map *map); 242int bpf_map__fd(struct bpf_map *map);
242const struct bpf_map_def *bpf_map__def(struct bpf_map *map); 243const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
243const char *bpf_map__name(struct bpf_map *map); 244const char *bpf_map__name(struct bpf_map *map);
245uint32_t bpf_map__btf_key_id(const struct bpf_map *map);
246uint32_t bpf_map__btf_value_id(const struct bpf_map *map);
244 247
245typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); 248typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
246int bpf_map__set_priv(struct bpf_map *map, void *priv, 249int bpf_map__set_priv(struct bpf_map *map, void *priv,