This allows BTF parsing to proceed even if we do not know the kind. Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx> --- tools/lib/bpf/btf.c | 50 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 036dc1505969..77a072716d58 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -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; -- 2.31.1