mirror of https://gitee.com/openkylin/linux.git
libbpf: Support flexible arrays in CO-RE
Some data stuctures in kernel are defined with either zero-sized array or flexible (dimensionless) array at the end of a struct. Actual data of such array follows in memory immediately after the end of that struct, forming its variable-sized "body" of elements. Support such access pattern in CO-RE relocation handling. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20191215070844.1014385-2-andriin@fb.com
This commit is contained in:
parent
01c6f7aaac
commit
1b484b301c
|
@ -3108,6 +3108,21 @@ static bool str_is_empty(const char *s)
|
||||||
return !s || !s[0];
|
return !s || !s[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_flex_arr(const struct btf *btf,
|
||||||
|
const struct bpf_core_accessor *acc,
|
||||||
|
const struct btf_array *arr)
|
||||||
|
{
|
||||||
|
const struct btf_type *t;
|
||||||
|
|
||||||
|
/* not a flexible array, if not inside a struct or has non-zero size */
|
||||||
|
if (!acc->name || arr->nelems > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* has to be the last member of enclosing struct */
|
||||||
|
t = btf__type_by_id(btf, acc->type_id);
|
||||||
|
return acc->idx == btf_vlen(t) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn bpf_field_reloc into a low- and high-level spec representation,
|
* Turn bpf_field_reloc into a low- and high-level spec representation,
|
||||||
* validating correctness along the way, as well as calculating resulting
|
* validating correctness along the way, as well as calculating resulting
|
||||||
|
@ -3145,6 +3160,7 @@ static int bpf_core_spec_parse(const struct btf *btf,
|
||||||
struct bpf_core_spec *spec)
|
struct bpf_core_spec *spec)
|
||||||
{
|
{
|
||||||
int access_idx, parsed_len, i;
|
int access_idx, parsed_len, i;
|
||||||
|
struct bpf_core_accessor *acc;
|
||||||
const struct btf_type *t;
|
const struct btf_type *t;
|
||||||
const char *name;
|
const char *name;
|
||||||
__u32 id;
|
__u32 id;
|
||||||
|
@ -3192,6 +3208,7 @@ static int bpf_core_spec_parse(const struct btf *btf,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
access_idx = spec->raw_spec[i];
|
access_idx = spec->raw_spec[i];
|
||||||
|
acc = &spec->spec[spec->len];
|
||||||
|
|
||||||
if (btf_is_composite(t)) {
|
if (btf_is_composite(t)) {
|
||||||
const struct btf_member *m;
|
const struct btf_member *m;
|
||||||
|
@ -3209,18 +3226,23 @@ static int bpf_core_spec_parse(const struct btf *btf,
|
||||||
if (str_is_empty(name))
|
if (str_is_empty(name))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spec->spec[spec->len].type_id = id;
|
acc->type_id = id;
|
||||||
spec->spec[spec->len].idx = access_idx;
|
acc->idx = access_idx;
|
||||||
spec->spec[spec->len].name = name;
|
acc->name = name;
|
||||||
spec->len++;
|
spec->len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = m->type;
|
id = m->type;
|
||||||
} else if (btf_is_array(t)) {
|
} else if (btf_is_array(t)) {
|
||||||
const struct btf_array *a = btf_array(t);
|
const struct btf_array *a = btf_array(t);
|
||||||
|
bool flex;
|
||||||
|
|
||||||
t = skip_mods_and_typedefs(btf, a->type, &id);
|
t = skip_mods_and_typedefs(btf, a->type, &id);
|
||||||
if (!t || access_idx >= a->nelems)
|
if (!t)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
flex = is_flex_arr(btf, acc - 1, a);
|
||||||
|
if (!flex && access_idx >= a->nelems)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spec->spec[spec->len].type_id = id;
|
spec->spec[spec->len].type_id = id;
|
||||||
|
@ -3525,12 +3547,14 @@ static int bpf_core_spec_match(struct bpf_core_spec *local_spec,
|
||||||
*/
|
*/
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
const struct btf_array *a;
|
const struct btf_array *a;
|
||||||
|
bool flex;
|
||||||
|
|
||||||
if (!btf_is_array(targ_type))
|
if (!btf_is_array(targ_type))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = btf_array(targ_type);
|
a = btf_array(targ_type);
|
||||||
if (local_acc->idx >= a->nelems)
|
flex = is_flex_arr(targ_btf, targ_acc - 1, a);
|
||||||
|
if (!flex && local_acc->idx >= a->nelems)
|
||||||
return 0;
|
return 0;
|
||||||
if (!skip_mods_and_typedefs(targ_btf, a->type,
|
if (!skip_mods_and_typedefs(targ_btf, a->type,
|
||||||
&targ_id))
|
&targ_id))
|
||||||
|
|
Loading…
Reference in New Issue