aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf/btf.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-04-11 20:00:05 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-11 20:00:05 -0400
commitbb23581b9b38703257acabd520aa5ebf1db008af (patch)
tree9d9f7b7ccad9697dfd2eab3b1fda37056b0e47f6 /tools/lib/bpf/btf.c
parent78f07adac86186b5ef0318b7faec377b6d31ea9f (diff)
parent947e8b595b82d3551750641445d0a97b8f29b536 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says: ==================== pull-request: bpf-next 2019-04-12 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) Improve BPF verifier scalability for large programs through two optimizations: i) remove verifier states that are not useful in pruning, ii) stop walking parentage chain once first LIVE_READ is seen. Combined gives approx 20x speedup. Increase limits for accepting large programs under root, and add various stress tests, from Alexei. 2) Implement global data support in BPF. This enables static global variables for .data, .rodata and .bss sections to be properly handled which allows for more natural program development. This also opens up the possibility to optimize program workflow by compiling ELFs only once and later only rewriting section data before reload, from Daniel and with test cases and libbpf refactoring from Joe. 3) Add config option to generate BTF type info for vmlinux as part of the kernel build process. DWARF debug info is converted via pahole to BTF. Latter relies on libbpf and makes use of BTF deduplication algorithm which results in 100x savings compared to DWARF data. Resulting .BTF section is typically about 2MB in size, from Andrii. 4) Add BPF verifier support for stack access with variable offset from helpers and add various test cases along with it, from Andrey. 5) Extend bpf_skb_adjust_room() growth BPF helper to mark inner MAC header so that L2 encapsulation can be used for tc tunnels, from Alan. 6) Add support for input __sk_buff context in BPF_PROG_TEST_RUN so that users can define a subset of allowed __sk_buff fields that get fed into the test program, from Stanislav. 7) Add bpf fs multi-dimensional array tests for BTF test suite and fix up various UBSAN warnings in bpftool, from Yonghong. 8) Generate a pkg-config file for libbpf, from Luca. 9) Dump program's BTF id in bpftool, from Prashant. 10) libbpf fix to use smaller BPF log buffer size for AF_XDP's XDP program, from Magnus. 11) kallsyms related fixes for the case when symbols are not present in BPF selftests and samples, from Daniel ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/lib/bpf/btf.c')
-rw-r--r--tools/lib/bpf/btf.c97
1 files changed, 96 insertions, 1 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index cf119c9b6f27..701e7e28ada3 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -24,6 +24,8 @@
24 ((k) == BTF_KIND_CONST) || \ 24 ((k) == BTF_KIND_CONST) || \
25 ((k) == BTF_KIND_RESTRICT)) 25 ((k) == BTF_KIND_RESTRICT))
26 26
27#define IS_VAR(k) ((k) == BTF_KIND_VAR)
28
27static struct btf_type btf_void; 29static struct btf_type btf_void;
28 30
29struct btf { 31struct btf {
@@ -212,6 +214,10 @@ static int btf_type_size(struct btf_type *t)
212 return base_size + vlen * sizeof(struct btf_member); 214 return base_size + vlen * sizeof(struct btf_member);
213 case BTF_KIND_FUNC_PROTO: 215 case BTF_KIND_FUNC_PROTO:
214 return base_size + vlen * sizeof(struct btf_param); 216 return base_size + vlen * sizeof(struct btf_param);
217 case BTF_KIND_VAR:
218 return base_size + sizeof(struct btf_var);
219 case BTF_KIND_DATASEC:
220 return base_size + vlen * sizeof(struct btf_var_secinfo);
215 default: 221 default:
216 pr_debug("Unsupported BTF_KIND:%u\n", BTF_INFO_KIND(t->info)); 222 pr_debug("Unsupported BTF_KIND:%u\n", BTF_INFO_KIND(t->info));
217 return -EINVAL; 223 return -EINVAL;
@@ -283,6 +289,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
283 case BTF_KIND_STRUCT: 289 case BTF_KIND_STRUCT:
284 case BTF_KIND_UNION: 290 case BTF_KIND_UNION:
285 case BTF_KIND_ENUM: 291 case BTF_KIND_ENUM:
292 case BTF_KIND_DATASEC:
286 size = t->size; 293 size = t->size;
287 goto done; 294 goto done;
288 case BTF_KIND_PTR: 295 case BTF_KIND_PTR:
@@ -292,6 +299,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
292 case BTF_KIND_VOLATILE: 299 case BTF_KIND_VOLATILE:
293 case BTF_KIND_CONST: 300 case BTF_KIND_CONST:
294 case BTF_KIND_RESTRICT: 301 case BTF_KIND_RESTRICT:
302 case BTF_KIND_VAR:
295 type_id = t->type; 303 type_id = t->type;
296 break; 304 break;
297 case BTF_KIND_ARRAY: 305 case BTF_KIND_ARRAY:
@@ -326,7 +334,8 @@ int btf__resolve_type(const struct btf *btf, __u32 type_id)
326 t = btf__type_by_id(btf, type_id); 334 t = btf__type_by_id(btf, type_id);
327 while (depth < MAX_RESOLVE_DEPTH && 335 while (depth < MAX_RESOLVE_DEPTH &&
328 !btf_type_is_void_or_null(t) && 336 !btf_type_is_void_or_null(t) &&
329 IS_MODIFIER(BTF_INFO_KIND(t->info))) { 337 (IS_MODIFIER(BTF_INFO_KIND(t->info)) ||
338 IS_VAR(BTF_INFO_KIND(t->info)))) {
330 type_id = t->type; 339 type_id = t->type;
331 t = btf__type_by_id(btf, type_id); 340 t = btf__type_by_id(btf, type_id);
332 depth++; 341 depth++;
@@ -408,6 +417,92 @@ done:
408 return btf; 417 return btf;
409} 418}
410 419
420static int compare_vsi_off(const void *_a, const void *_b)
421{
422 const struct btf_var_secinfo *a = _a;
423 const struct btf_var_secinfo *b = _b;
424
425 return a->offset - b->offset;
426}
427
428static int btf_fixup_datasec(struct bpf_object *obj, struct btf *btf,
429 struct btf_type *t)
430{
431 __u32 size = 0, off = 0, i, vars = BTF_INFO_VLEN(t->info);
432 const char *name = btf__name_by_offset(btf, t->name_off);
433 const struct btf_type *t_var;
434 struct btf_var_secinfo *vsi;
435 struct btf_var *var;
436 int ret;
437
438 if (!name) {
439 pr_debug("No name found in string section for DATASEC kind.\n");
440 return -ENOENT;
441 }
442
443 ret = bpf_object__section_size(obj, name, &size);
444 if (ret || !size || (t->size && t->size != size)) {
445 pr_debug("Invalid size for section %s: %u bytes\n", name, size);
446 return -ENOENT;
447 }
448
449 t->size = size;
450
451 for (i = 0, vsi = (struct btf_var_secinfo *)(t + 1);
452 i < vars; i++, vsi++) {
453 t_var = btf__type_by_id(btf, vsi->type);
454 var = (struct btf_var *)(t_var + 1);
455
456 if (BTF_INFO_KIND(t_var->info) != BTF_KIND_VAR) {
457 pr_debug("Non-VAR type seen in section %s\n", name);
458 return -EINVAL;
459 }
460
461 if (var->linkage == BTF_VAR_STATIC)
462 continue;
463
464 name = btf__name_by_offset(btf, t_var->name_off);
465 if (!name) {
466 pr_debug("No name found in string section for VAR kind\n");
467 return -ENOENT;
468 }
469
470 ret = bpf_object__variable_offset(obj, name, &off);
471 if (ret) {
472 pr_debug("No offset found in symbol table for VAR %s\n", name);
473 return -ENOENT;
474 }
475
476 vsi->offset = off;
477 }
478
479 qsort(t + 1, vars, sizeof(*vsi), compare_vsi_off);
480 return 0;
481}
482
483int btf__finalize_data(struct bpf_object *obj, struct btf *btf)
484{
485 int err = 0;
486 __u32 i;
487
488 for (i = 1; i <= btf->nr_types; i++) {
489 struct btf_type *t = btf->types[i];
490
491 /* Loader needs to fix up some of the things compiler
492 * couldn't get its hands on while emitting BTF. This
493 * is section size and global variable offset. We use
494 * the info from the ELF itself for this purpose.
495 */
496 if (BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC) {
497 err = btf_fixup_datasec(obj, btf, t);
498 if (err)
499 break;
500 }
501 }
502
503 return err;
504}
505
411int btf__load(struct btf *btf) 506int btf__load(struct btf *btf)
412{ 507{
413 __u32 log_buf_size = BPF_LOG_BUF_SIZE; 508 __u32 log_buf_size = BPF_LOG_BUF_SIZE;