diff options
author | Yonghong Song <yhs@fb.com> | 2019-02-04 14:00:58 -0500 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2019-02-04 15:48:36 -0500 |
commit | 96408c43447aff5091a6938f29d8b6f2d0aa2064 (patch) | |
tree | e59397b34c18fbca196e149502381e4efa1ad31c /tools/lib/bpf/btf.c | |
parent | b8dcf8d149db5999d3db937822d3e374eca68b9f (diff) |
tools/bpf: implement libbpf btf__get_map_kv_tids() API function
Currently, to get map key/value type id's, the macro
BPF_ANNOTATE_KV_PAIR(<map_name>, <key_type>, <value_type>)
needs to be defined in the bpf program for the
corresponding map.
During program/map loading time,
the local static function bpf_map_find_btf_info()
in libbpf.c is implemented to retrieve the key/value
type ids given the map name.
The patch refactored function bpf_map_find_btf_info()
to create an API btf__get_map_kv_tids() which includes
the bulk of implementation for the original function.
The API btf__get_map_kv_tids() can be used by bcc,
a JIT based bpf compilation system, which uses the
same BPF_ANNOTATE_KV_PAIR to record map key/value types.
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/lib/bpf/btf.c')
-rw-r--r-- | tools/lib/bpf/btf.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 51a0db05bf80..7ec0463354db 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c | |||
@@ -1,6 +1,7 @@ | |||
1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) |
2 | /* Copyright (c) 2018 Facebook */ | 2 | /* Copyright (c) 2018 Facebook */ |
3 | 3 | ||
4 | #include <stdio.h> | ||
4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
5 | #include <string.h> | 6 | #include <string.h> |
6 | #include <unistd.h> | 7 | #include <unistd.h> |
@@ -504,6 +505,78 @@ exit_free: | |||
504 | return err; | 505 | return err; |
505 | } | 506 | } |
506 | 507 | ||
508 | int btf__get_map_kv_tids(const struct btf *btf, char *map_name, | ||
509 | __u32 expected_key_size, __u32 expected_value_size, | ||
510 | __u32 *key_type_id, __u32 *value_type_id) | ||
511 | { | ||
512 | const struct btf_type *container_type; | ||
513 | const struct btf_member *key, *value; | ||
514 | const size_t max_name = 256; | ||
515 | char container_name[max_name]; | ||
516 | __s64 key_size, value_size; | ||
517 | __s32 container_id; | ||
518 | |||
519 | if (snprintf(container_name, max_name, "____btf_map_%s", map_name) == | ||
520 | max_name) { | ||
521 | pr_warning("map:%s length of '____btf_map_%s' is too long\n", | ||
522 | map_name, map_name); | ||
523 | return -EINVAL; | ||
524 | } | ||
525 | |||
526 | container_id = btf__find_by_name(btf, container_name); | ||
527 | if (container_id < 0) { | ||
528 | pr_warning("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n", | ||
529 | map_name, container_name); | ||
530 | return container_id; | ||
531 | } | ||
532 | |||
533 | container_type = btf__type_by_id(btf, container_id); | ||
534 | if (!container_type) { | ||
535 | pr_warning("map:%s cannot find BTF type for container_id:%u\n", | ||
536 | map_name, container_id); | ||
537 | return -EINVAL; | ||
538 | } | ||
539 | |||
540 | if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT || | ||
541 | BTF_INFO_VLEN(container_type->info) < 2) { | ||
542 | pr_warning("map:%s container_name:%s is an invalid container struct\n", | ||
543 | map_name, container_name); | ||
544 | return -EINVAL; | ||
545 | } | ||
546 | |||
547 | key = (struct btf_member *)(container_type + 1); | ||
548 | value = key + 1; | ||
549 | |||
550 | key_size = btf__resolve_size(btf, key->type); | ||
551 | if (key_size < 0) { | ||
552 | pr_warning("map:%s invalid BTF key_type_size\n", map_name); | ||
553 | return key_size; | ||
554 | } | ||
555 | |||
556 | if (expected_key_size != key_size) { | ||
557 | pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n", | ||
558 | map_name, (__u32)key_size, expected_key_size); | ||
559 | return -EINVAL; | ||
560 | } | ||
561 | |||
562 | value_size = btf__resolve_size(btf, value->type); | ||
563 | if (value_size < 0) { | ||
564 | pr_warning("map:%s invalid BTF value_type_size\n", map_name); | ||
565 | return value_size; | ||
566 | } | ||
567 | |||
568 | if (expected_value_size != value_size) { | ||
569 | pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n", | ||
570 | map_name, (__u32)value_size, expected_value_size); | ||
571 | return -EINVAL; | ||
572 | } | ||
573 | |||
574 | *key_type_id = key->type; | ||
575 | *value_type_id = value->type; | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
507 | struct btf_ext_sec_copy_param { | 580 | struct btf_ext_sec_copy_param { |
508 | __u32 off; | 581 | __u32 off; |
509 | __u32 len; | 582 | __u32 len; |