@@ -336,7 +336,40 @@ static int btf_parse_meta_sec(struct btf *btf)
return 0;
}
-static int btf_type_size(const struct btf_type *t)
+/* for unknown kinds, consult kind metadata. */
+static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t)
+{
+ int size = sizeof(struct btf_type);
+ struct btf_kind_meta *m = NULL;
+ __u16 vlen = btf_vlen(t);
+ __u8 kind = btf_kind(t);
+
+ if (btf->meta_data) {
+ struct btf_metadata *meta = btf->meta_data;
+
+ if (kind < meta->kind_meta_cnt)
+ m = &meta->kind_meta[kind];
+ }
+
+ if (!m || (void *)m > (btf->meta_data + btf->hdr->meta_header.meta_len)) {
+ pr_debug("Unsupported BTF_KIND: %u\n", btf_kind(t));
+ return -EINVAL;
+ }
+
+ if (!(m->flags & BTF_KIND_META_OPTIONAL)) {
+ /* a required kind, and we do not know about it.. */
+ pr_debug("unknown but required kind: %s(%u)\n",
+ btf__name_by_offset(btf, m->name_off), kind);
+ return -EINVAL;
+ }
+
+ size += m->info_sz;
+ size += vlen * m->elem_sz;
+
+ return size;
+}
+
+static int btf_type_size(const struct btf *btf, const struct btf_type *t)
{
const int base_size = sizeof(struct btf_type);
__u16 vlen = btf_vlen(t);
@@ -372,8 +405,7 @@ static int btf_type_size(const struct btf_type *t)
case BTF_KIND_DECL_TAG:
return base_size + sizeof(struct btf_decl_tag);
default:
- pr_debug("Unsupported BTF_KIND:%u\n", btf_kind(t));
- return -EINVAL;
+ return btf_type_size_unknown(btf, t);
}
}
@@ -472,7 +504,7 @@ static int btf_parse_type_sec(struct btf *btf)
if (btf->swapped_endian)
btf_bswap_type_base(next_type);
- type_size = btf_type_size(next_type);
+ type_size = btf_type_size(btf, next_type);
if (type_size < 0)
return type_size;
if (next_type + type_size > end_type) {
@@ -952,10 +984,8 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
btf->types_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->type_off;
err = btf_parse_str_sec(btf);
+ err = err ?: btf_parse_meta_sec(btf);
err = err ?: btf_parse_type_sec(btf);
- if (err)
- goto done;
- err = btf_parse_meta_sec(btf);
done:
if (err) {
@@ -1687,7 +1717,7 @@ int btf__add_type(struct btf *btf, const struct btf *src_btf, const struct btf_t
struct btf_type *t;
int sz, err;
- sz = btf_type_size(src_type);
+ sz = btf_type_size(src_btf, src_type);
if (sz < 0)
return libbpf_err(sz);
@@ -1768,7 +1798,7 @@ int btf__add_btf(struct btf *btf, const struct btf *src_btf)
memcpy(t, src_btf->types_data, data_sz);
for (i = 0; i < cnt; i++) {
- sz = btf_type_size(t);
+ sz = btf_type_size(src_btf, t);
if (sz < 0) {
/* unlikely, has to be corrupted src_btf */
err = sz;
@@ -4764,7 +4794,7 @@ static int btf_dedup_compact_types(struct btf_dedup *d)
continue;
t = btf__type_by_id(d->btf, id);
- len = btf_type_size(t);
+ len = btf_type_size(d->btf, t);
if (len < 0)
return len;
This allows BTF parsing to proceed even if we do not know the kind. Signed-off-by: Alan Maguire <alan.maguire@oracle.com> --- tools/lib/bpf/btf.c | 50 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 10 deletions(-)