diff options
author | Andrii Nakryiko <andriin@fb.com> | 2019-02-08 14:19:38 -0500 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2019-02-08 15:04:13 -0500 |
commit | ae4ab4b4117d23da49f04a7e1fe82a41e6074eeb (patch) | |
tree | ad5082a6f997ab16fadfbea5fb31f457d04e7eda /tools/lib/bpf/btf.c | |
parent | 02c874460f3d9213096323ac8a937fb486a4e70d (diff) |
btf: expose API to work with raw btf_ext data
This patch changes struct btf_ext to retain original data in sequential
block of memory, which makes it possible to expose
btf_ext__get_raw_data() interface similar to btf__get_raw_data(), allowing
users of libbpf to get access to raw representation of .BTF.ext section.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-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 | 102 |
1 files changed, 54 insertions, 48 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 4fba0aa989df..f6b724ed1bdd 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c | |||
@@ -42,9 +42,8 @@ struct btf { | |||
42 | 42 | ||
43 | struct btf_ext_info { | 43 | struct btf_ext_info { |
44 | /* | 44 | /* |
45 | * info points to a deep copy of the individual info section | 45 | * info points to the individual info section (e.g. func_info and |
46 | * (e.g. func_info and line_info) from the .BTF.ext. | 46 | * line_info) from the .BTF.ext. It does not include the __u32 rec_size. |
47 | * It does not include the __u32 rec_size. | ||
48 | */ | 47 | */ |
49 | void *info; | 48 | void *info; |
50 | __u32 rec_size; | 49 | __u32 rec_size; |
@@ -52,8 +51,13 @@ struct btf_ext_info { | |||
52 | }; | 51 | }; |
53 | 52 | ||
54 | struct btf_ext { | 53 | struct btf_ext { |
54 | union { | ||
55 | struct btf_ext_header *hdr; | ||
56 | void *data; | ||
57 | }; | ||
55 | struct btf_ext_info func_info; | 58 | struct btf_ext_info func_info; |
56 | struct btf_ext_info line_info; | 59 | struct btf_ext_info line_info; |
60 | __u32 data_size; | ||
57 | }; | 61 | }; |
58 | 62 | ||
59 | struct btf_ext_info_sec { | 63 | struct btf_ext_info_sec { |
@@ -596,7 +600,7 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name, | |||
596 | return 0; | 600 | return 0; |
597 | } | 601 | } |
598 | 602 | ||
599 | struct btf_ext_sec_copy_param { | 603 | struct btf_ext_sec_setup_param { |
600 | __u32 off; | 604 | __u32 off; |
601 | __u32 len; | 605 | __u32 len; |
602 | __u32 min_rec_size; | 606 | __u32 min_rec_size; |
@@ -604,20 +608,14 @@ struct btf_ext_sec_copy_param { | |||
604 | const char *desc; | 608 | const char *desc; |
605 | }; | 609 | }; |
606 | 610 | ||
607 | static int btf_ext_copy_info(struct btf_ext *btf_ext, | 611 | static int btf_ext_setup_info(struct btf_ext *btf_ext, |
608 | __u8 *data, __u32 data_size, | 612 | struct btf_ext_sec_setup_param *ext_sec) |
609 | struct btf_ext_sec_copy_param *ext_sec) | ||
610 | { | 613 | { |
611 | const struct btf_ext_header *hdr = (struct btf_ext_header *)data; | ||
612 | const struct btf_ext_info_sec *sinfo; | 614 | const struct btf_ext_info_sec *sinfo; |
613 | struct btf_ext_info *ext_info; | 615 | struct btf_ext_info *ext_info; |
614 | __u32 info_left, record_size; | 616 | __u32 info_left, record_size; |
615 | /* The start of the info sec (including the __u32 record_size). */ | 617 | /* The start of the info sec (including the __u32 record_size). */ |
616 | const void *info; | 618 | void *info; |
617 | |||
618 | /* data and data_size do not include btf_ext_header from now on */ | ||
619 | data = data + hdr->hdr_len; | ||
620 | data_size -= hdr->hdr_len; | ||
621 | 619 | ||
622 | if (ext_sec->off & 0x03) { | 620 | if (ext_sec->off & 0x03) { |
623 | pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n", | 621 | pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n", |
@@ -625,16 +623,15 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext, | |||
625 | return -EINVAL; | 623 | return -EINVAL; |
626 | } | 624 | } |
627 | 625 | ||
628 | if (data_size < ext_sec->off || | 626 | info = btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off; |
629 | ext_sec->len > data_size - ext_sec->off) { | 627 | info_left = ext_sec->len; |
628 | |||
629 | if (btf_ext->data + btf_ext->data_size < info + ext_sec->len) { | ||
630 | pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n", | 630 | pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n", |
631 | ext_sec->desc, ext_sec->off, ext_sec->len); | 631 | ext_sec->desc, ext_sec->off, ext_sec->len); |
632 | return -EINVAL; | 632 | return -EINVAL; |
633 | } | 633 | } |
634 | 634 | ||
635 | info = data + ext_sec->off; | ||
636 | info_left = ext_sec->len; | ||
637 | |||
638 | /* At least a record size */ | 635 | /* At least a record size */ |
639 | if (info_left < sizeof(__u32)) { | 636 | if (info_left < sizeof(__u32)) { |
640 | pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc); | 637 | pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc); |
@@ -646,7 +643,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext, | |||
646 | if (record_size < ext_sec->min_rec_size || | 643 | if (record_size < ext_sec->min_rec_size || |
647 | record_size & 0x03) { | 644 | record_size & 0x03) { |
648 | pr_debug("%s section in .BTF.ext has invalid record size %u\n", | 645 | pr_debug("%s section in .BTF.ext has invalid record size %u\n", |
649 | ext_sec->desc, record_size); | 646 | ext_sec->desc, record_size); |
650 | return -EINVAL; | 647 | return -EINVAL; |
651 | } | 648 | } |
652 | 649 | ||
@@ -692,42 +689,35 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext, | |||
692 | ext_info = ext_sec->ext_info; | 689 | ext_info = ext_sec->ext_info; |
693 | ext_info->len = ext_sec->len - sizeof(__u32); | 690 | ext_info->len = ext_sec->len - sizeof(__u32); |
694 | ext_info->rec_size = record_size; | 691 | ext_info->rec_size = record_size; |
695 | ext_info->info = malloc(ext_info->len); | 692 | ext_info->info = info + sizeof(__u32); |
696 | if (!ext_info->info) | ||
697 | return -ENOMEM; | ||
698 | memcpy(ext_info->info, info + sizeof(__u32), ext_info->len); | ||
699 | 693 | ||
700 | return 0; | 694 | return 0; |
701 | } | 695 | } |
702 | 696 | ||
703 | static int btf_ext_copy_func_info(struct btf_ext *btf_ext, | 697 | static int btf_ext_setup_func_info(struct btf_ext *btf_ext) |
704 | __u8 *data, __u32 data_size) | ||
705 | { | 698 | { |
706 | const struct btf_ext_header *hdr = (struct btf_ext_header *)data; | 699 | struct btf_ext_sec_setup_param param = { |
707 | struct btf_ext_sec_copy_param param = { | 700 | .off = btf_ext->hdr->func_info_off, |
708 | .off = hdr->func_info_off, | 701 | .len = btf_ext->hdr->func_info_len, |
709 | .len = hdr->func_info_len, | ||
710 | .min_rec_size = sizeof(struct bpf_func_info_min), | 702 | .min_rec_size = sizeof(struct bpf_func_info_min), |
711 | .ext_info = &btf_ext->func_info, | 703 | .ext_info = &btf_ext->func_info, |
712 | .desc = "func_info" | 704 | .desc = "func_info" |
713 | }; | 705 | }; |
714 | 706 | ||
715 | return btf_ext_copy_info(btf_ext, data, data_size, ¶m); | 707 | return btf_ext_setup_info(btf_ext, ¶m); |
716 | } | 708 | } |
717 | 709 | ||
718 | static int btf_ext_copy_line_info(struct btf_ext *btf_ext, | 710 | static int btf_ext_setup_line_info(struct btf_ext *btf_ext) |
719 | __u8 *data, __u32 data_size) | ||
720 | { | 711 | { |
721 | const struct btf_ext_header *hdr = (struct btf_ext_header *)data; | 712 | struct btf_ext_sec_setup_param param = { |
722 | struct btf_ext_sec_copy_param param = { | 713 | .off = btf_ext->hdr->line_info_off, |
723 | .off = hdr->line_info_off, | 714 | .len = btf_ext->hdr->line_info_len, |
724 | .len = hdr->line_info_len, | ||
725 | .min_rec_size = sizeof(struct bpf_line_info_min), | 715 | .min_rec_size = sizeof(struct bpf_line_info_min), |
726 | .ext_info = &btf_ext->line_info, | 716 | .ext_info = &btf_ext->line_info, |
727 | .desc = "line_info", | 717 | .desc = "line_info", |
728 | }; | 718 | }; |
729 | 719 | ||
730 | return btf_ext_copy_info(btf_ext, data, data_size, ¶m); | 720 | return btf_ext_setup_info(btf_ext, ¶m); |
731 | } | 721 | } |
732 | 722 | ||
733 | static int btf_ext_parse_hdr(__u8 *data, __u32 data_size) | 723 | static int btf_ext_parse_hdr(__u8 *data, __u32 data_size) |
@@ -767,9 +757,7 @@ void btf_ext__free(struct btf_ext *btf_ext) | |||
767 | { | 757 | { |
768 | if (!btf_ext) | 758 | if (!btf_ext) |
769 | return; | 759 | return; |
770 | 760 | free(btf_ext->data); | |
771 | free(btf_ext->func_info.info); | ||
772 | free(btf_ext->line_info.info); | ||
773 | free(btf_ext); | 761 | free(btf_ext); |
774 | } | 762 | } |
775 | 763 | ||
@@ -786,13 +774,23 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size) | |||
786 | if (!btf_ext) | 774 | if (!btf_ext) |
787 | return ERR_PTR(-ENOMEM); | 775 | return ERR_PTR(-ENOMEM); |
788 | 776 | ||
789 | err = btf_ext_copy_func_info(btf_ext, data, size); | 777 | btf_ext->data_size = size; |
790 | if (err) { | 778 | btf_ext->data = malloc(size); |
791 | btf_ext__free(btf_ext); | 779 | if (!btf_ext->data) { |
792 | return ERR_PTR(err); | 780 | err = -ENOMEM; |
781 | goto done; | ||
793 | } | 782 | } |
783 | memcpy(btf_ext->data, data, size); | ||
784 | |||
785 | err = btf_ext_setup_func_info(btf_ext); | ||
786 | if (err) | ||
787 | goto done; | ||
794 | 788 | ||
795 | err = btf_ext_copy_line_info(btf_ext, data, size); | 789 | err = btf_ext_setup_line_info(btf_ext); |
790 | if (err) | ||
791 | goto done; | ||
792 | |||
793 | done: | ||
796 | if (err) { | 794 | if (err) { |
797 | btf_ext__free(btf_ext); | 795 | btf_ext__free(btf_ext); |
798 | return ERR_PTR(err); | 796 | return ERR_PTR(err); |
@@ -801,6 +799,12 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size) | |||
801 | return btf_ext; | 799 | return btf_ext; |
802 | } | 800 | } |
803 | 801 | ||
802 | const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, __u32 *size) | ||
803 | { | ||
804 | *size = btf_ext->data_size; | ||
805 | return btf_ext->data; | ||
806 | } | ||
807 | |||
804 | static int btf_ext_reloc_info(const struct btf *btf, | 808 | static int btf_ext_reloc_info(const struct btf *btf, |
805 | const struct btf_ext_info *ext_info, | 809 | const struct btf_ext_info *ext_info, |
806 | const char *sec_name, __u32 insns_cnt, | 810 | const char *sec_name, __u32 insns_cnt, |
@@ -849,7 +853,8 @@ static int btf_ext_reloc_info(const struct btf *btf, | |||
849 | return -ENOENT; | 853 | return -ENOENT; |
850 | } | 854 | } |
851 | 855 | ||
852 | int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ext, | 856 | int btf_ext__reloc_func_info(const struct btf *btf, |
857 | const struct btf_ext *btf_ext, | ||
853 | const char *sec_name, __u32 insns_cnt, | 858 | const char *sec_name, __u32 insns_cnt, |
854 | void **func_info, __u32 *cnt) | 859 | void **func_info, __u32 *cnt) |
855 | { | 860 | { |
@@ -857,7 +862,8 @@ int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ex | |||
857 | insns_cnt, func_info, cnt); | 862 | insns_cnt, func_info, cnt); |
858 | } | 863 | } |
859 | 864 | ||
860 | int btf_ext__reloc_line_info(const struct btf *btf, const struct btf_ext *btf_ext, | 865 | int btf_ext__reloc_line_info(const struct btf *btf, |
866 | const struct btf_ext *btf_ext, | ||
861 | const char *sec_name, __u32 insns_cnt, | 867 | const char *sec_name, __u32 insns_cnt, |
862 | void **line_info, __u32 *cnt) | 868 | void **line_info, __u32 *cnt) |
863 | { | 869 | { |