btf: extract BTF type size calculation

This pre-patch extracts calculation of amount of space taken by BTF type descriptor
for later reuse by btf_dedup functionality.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
Andrii Nakryiko 2019-02-04 17:29:44 -08:00 committed by Daniel Borkmann
parent a8a1f7d09c
commit 69eaab04c6

View file

@ -182,6 +182,37 @@ static int btf_parse_str_sec(struct btf *btf)
return 0;
}
static int btf_type_size(struct btf_type *t)
{
int base_size = sizeof(struct btf_type);
__u16 vlen = BTF_INFO_VLEN(t->info);
switch (BTF_INFO_KIND(t->info)) {
case BTF_KIND_FWD:
case BTF_KIND_CONST:
case BTF_KIND_VOLATILE:
case BTF_KIND_RESTRICT:
case BTF_KIND_PTR:
case BTF_KIND_TYPEDEF:
case BTF_KIND_FUNC:
return base_size;
case BTF_KIND_INT:
return base_size + sizeof(__u32);
case BTF_KIND_ENUM:
return base_size + vlen * sizeof(struct btf_enum);
case BTF_KIND_ARRAY:
return base_size + sizeof(struct btf_array);
case BTF_KIND_STRUCT:
case BTF_KIND_UNION:
return base_size + vlen * sizeof(struct btf_member);
case BTF_KIND_FUNC_PROTO:
return base_size + vlen * sizeof(struct btf_param);
default:
pr_debug("Unsupported BTF_KIND:%u\n", BTF_INFO_KIND(t->info));
return -EINVAL;
}
}
static int btf_parse_type_sec(struct btf *btf)
{
struct btf_header *hdr = btf->hdr;
@ -191,41 +222,13 @@ static int btf_parse_type_sec(struct btf *btf)
while (next_type < end_type) {
struct btf_type *t = next_type;
__u16 vlen = BTF_INFO_VLEN(t->info);
int type_size;
int err;
next_type += sizeof(*t);
switch (BTF_INFO_KIND(t->info)) {
case BTF_KIND_INT:
next_type += sizeof(int);
break;
case BTF_KIND_ARRAY:
next_type += sizeof(struct btf_array);
break;
case BTF_KIND_STRUCT:
case BTF_KIND_UNION:
next_type += vlen * sizeof(struct btf_member);
break;
case BTF_KIND_ENUM:
next_type += vlen * sizeof(struct btf_enum);
break;
case BTF_KIND_FUNC_PROTO:
next_type += vlen * sizeof(struct btf_param);
break;
case BTF_KIND_FUNC:
case BTF_KIND_TYPEDEF:
case BTF_KIND_PTR:
case BTF_KIND_FWD:
case BTF_KIND_VOLATILE:
case BTF_KIND_CONST:
case BTF_KIND_RESTRICT:
break;
default:
pr_debug("Unsupported BTF_KIND:%u\n",
BTF_INFO_KIND(t->info));
return -EINVAL;
}
type_size = btf_type_size(t);
if (type_size < 0)
return type_size;
next_type += type_size;
err = btf_add_type(btf, t);
if (err)
return err;
@ -252,21 +255,6 @@ static bool btf_type_is_void_or_null(const struct btf_type *t)
return !t || btf_type_is_void(t);
}
static __s64 btf_type_size(const struct btf_type *t)
{
switch (BTF_INFO_KIND(t->info)) {
case BTF_KIND_INT:
case BTF_KIND_STRUCT:
case BTF_KIND_UNION:
case BTF_KIND_ENUM:
return t->size;
case BTF_KIND_PTR:
return sizeof(void *);
default:
return -EINVAL;
}
}
#define MAX_RESOLVE_DEPTH 32
__s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
@ -280,11 +268,16 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
t = btf__type_by_id(btf, type_id);
for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);
i++) {
size = btf_type_size(t);
if (size >= 0)
break;
switch (BTF_INFO_KIND(t->info)) {
case BTF_KIND_INT:
case BTF_KIND_STRUCT:
case BTF_KIND_UNION:
case BTF_KIND_ENUM:
size = t->size;
goto done;
case BTF_KIND_PTR:
size = sizeof(void *);
goto done;
case BTF_KIND_TYPEDEF:
case BTF_KIND_VOLATILE:
case BTF_KIND_CONST:
@ -308,6 +301,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
if (size < 0)
return -EINVAL;
done:
if (nelems && size > UINT32_MAX / nelems)
return -E2BIG;