aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf/libbpf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r--tools/lib/bpf/libbpf.c150
1 files changed, 131 insertions, 19 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index f7b245fbb960..e2a457e7c318 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -669,6 +669,112 @@ static bool bpf_map_type__is_map_in_map(enum bpf_map_type type)
669 return false; 669 return false;
670} 670}
671 671
672static int bpf_object_search_section_size(const struct bpf_object *obj,
673 const char *name, size_t *d_size)
674{
675 const GElf_Ehdr *ep = &obj->efile.ehdr;
676 Elf *elf = obj->efile.elf;
677 Elf_Scn *scn = NULL;
678 int idx = 0;
679
680 while ((scn = elf_nextscn(elf, scn)) != NULL) {
681 const char *sec_name;
682 Elf_Data *data;
683 GElf_Shdr sh;
684
685 idx++;
686 if (gelf_getshdr(scn, &sh) != &sh) {
687 pr_warning("failed to get section(%d) header from %s\n",
688 idx, obj->path);
689 return -EIO;
690 }
691
692 sec_name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
693 if (!sec_name) {
694 pr_warning("failed to get section(%d) name from %s\n",
695 idx, obj->path);
696 return -EIO;
697 }
698
699 if (strcmp(name, sec_name))
700 continue;
701
702 data = elf_getdata(scn, 0);
703 if (!data) {
704 pr_warning("failed to get section(%d) data from %s(%s)\n",
705 idx, name, obj->path);
706 return -EIO;
707 }
708
709 *d_size = data->d_size;
710 return 0;
711 }
712
713 return -ENOENT;
714}
715
716int bpf_object__section_size(const struct bpf_object *obj, const char *name,
717 __u32 *size)
718{
719 int ret = -ENOENT;
720 size_t d_size;
721
722 *size = 0;
723 if (!name) {
724 return -EINVAL;
725 } else if (!strcmp(name, ".data")) {
726 if (obj->efile.data)
727 *size = obj->efile.data->d_size;
728 } else if (!strcmp(name, ".bss")) {
729 if (obj->efile.bss)
730 *size = obj->efile.bss->d_size;
731 } else if (!strcmp(name, ".rodata")) {
732 if (obj->efile.rodata)
733 *size = obj->efile.rodata->d_size;
734 } else {
735 ret = bpf_object_search_section_size(obj, name, &d_size);
736 if (!ret)
737 *size = d_size;
738 }
739
740 return *size ? 0 : ret;
741}
742
743int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
744 __u32 *off)
745{
746 Elf_Data *symbols = obj->efile.symbols;
747 const char *sname;
748 size_t si;
749
750 if (!name || !off)
751 return -EINVAL;
752
753 for (si = 0; si < symbols->d_size / sizeof(GElf_Sym); si++) {
754 GElf_Sym sym;
755
756 if (!gelf_getsym(symbols, si, &sym))
757 continue;
758 if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
759 GELF_ST_TYPE(sym.st_info) != STT_OBJECT)
760 continue;
761
762 sname = elf_strptr(obj->efile.elf, obj->efile.strtabidx,
763 sym.st_name);
764 if (!sname) {
765 pr_warning("failed to get sym name string for var %s\n",
766 name);
767 return -EIO;
768 }
769 if (strcmp(name, sname) == 0) {
770 *off = sym.st_value;
771 return 0;
772 }
773 }
774
775 return -ENOENT;
776}
777
672static bool bpf_object__has_maps(const struct bpf_object *obj) 778static bool bpf_object__has_maps(const struct bpf_object *obj)
673{ 779{
674 return obj->efile.maps_shndx >= 0 || 780 return obj->efile.maps_shndx >= 0 ||
@@ -911,6 +1017,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
911 Elf *elf = obj->efile.elf; 1017 Elf *elf = obj->efile.elf;
912 GElf_Ehdr *ep = &obj->efile.ehdr; 1018 GElf_Ehdr *ep = &obj->efile.ehdr;
913 Elf_Data *btf_ext_data = NULL; 1019 Elf_Data *btf_ext_data = NULL;
1020 Elf_Data *btf_data = NULL;
914 Elf_Scn *scn = NULL; 1021 Elf_Scn *scn = NULL;
915 int idx = 0, err = 0; 1022 int idx = 0, err = 0;
916 1023
@@ -954,32 +1061,18 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
954 (int)sh.sh_link, (unsigned long)sh.sh_flags, 1061 (int)sh.sh_link, (unsigned long)sh.sh_flags,
955 (int)sh.sh_type); 1062 (int)sh.sh_type);
956 1063
957 if (strcmp(name, "license") == 0) 1064 if (strcmp(name, "license") == 0) {
958 err = bpf_object__init_license(obj, 1065 err = bpf_object__init_license(obj,
959 data->d_buf, 1066 data->d_buf,
960 data->d_size); 1067 data->d_size);
961 else if (strcmp(name, "version") == 0) 1068 } else if (strcmp(name, "version") == 0) {
962 err = bpf_object__init_kversion(obj, 1069 err = bpf_object__init_kversion(obj,
963 data->d_buf, 1070 data->d_buf,
964 data->d_size); 1071 data->d_size);
965 else if (strcmp(name, "maps") == 0) 1072 } else if (strcmp(name, "maps") == 0) {
966 obj->efile.maps_shndx = idx; 1073 obj->efile.maps_shndx = idx;
967 else if (strcmp(name, BTF_ELF_SEC) == 0) { 1074 } else if (strcmp(name, BTF_ELF_SEC) == 0) {
968 obj->btf = btf__new(data->d_buf, data->d_size); 1075 btf_data = data;
969 if (IS_ERR(obj->btf)) {
970 pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
971 BTF_ELF_SEC, PTR_ERR(obj->btf));
972 obj->btf = NULL;
973 continue;
974 }
975 err = btf__load(obj->btf);
976 if (err) {
977 pr_warning("Error loading %s into kernel: %d. Ignored and continue.\n",
978 BTF_ELF_SEC, err);
979 btf__free(obj->btf);
980 obj->btf = NULL;
981 err = 0;
982 }
983 } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { 1076 } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {
984 btf_ext_data = data; 1077 btf_ext_data = data;
985 } else if (sh.sh_type == SHT_SYMTAB) { 1078 } else if (sh.sh_type == SHT_SYMTAB) {
@@ -1054,6 +1147,25 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
1054 pr_warning("Corrupted ELF file: index of strtab invalid\n"); 1147 pr_warning("Corrupted ELF file: index of strtab invalid\n");
1055 return LIBBPF_ERRNO__FORMAT; 1148 return LIBBPF_ERRNO__FORMAT;
1056 } 1149 }
1150 if (btf_data) {
1151 obj->btf = btf__new(btf_data->d_buf, btf_data->d_size);
1152 if (IS_ERR(obj->btf)) {
1153 pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
1154 BTF_ELF_SEC, PTR_ERR(obj->btf));
1155 obj->btf = NULL;
1156 } else {
1157 err = btf__finalize_data(obj, obj->btf);
1158 if (!err)
1159 err = btf__load(obj->btf);
1160 if (err) {
1161 pr_warning("Error finalizing and loading %s into kernel: %d. Ignored and continue.\n",
1162 BTF_ELF_SEC, err);
1163 btf__free(obj->btf);
1164 obj->btf = NULL;
1165 err = 0;
1166 }
1167 }
1168 }
1057 if (btf_ext_data) { 1169 if (btf_ext_data) {
1058 if (!obj->btf) { 1170 if (!obj->btf) {
1059 pr_debug("Ignore ELF section %s because its depending ELF section %s is not found.\n", 1171 pr_debug("Ignore ELF section %s because its depending ELF section %s is not found.\n",