bpf: refactor btf_find_struct_field() and btf_find_datasec_var().
Move common code of the two functions to btf_find_field_one(). Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com> Link: https://lore.kernel.org/r/20240523174202.461236-4-thinker.li@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
482f713379
commit
a7db0d4f87
180
kernel/bpf/btf.c
180
kernel/bpf/btf.c
@ -3494,72 +3494,95 @@ end:
|
||||
|
||||
#undef field_mask_test_name
|
||||
|
||||
static int btf_find_field_one(const struct btf *btf,
|
||||
const struct btf_type *var,
|
||||
const struct btf_type *var_type,
|
||||
int var_idx,
|
||||
u32 off, u32 expected_size,
|
||||
u32 field_mask, u32 *seen_mask,
|
||||
struct btf_field_info *info, int info_cnt)
|
||||
{
|
||||
int ret, align, sz, field_type;
|
||||
struct btf_field_info tmp;
|
||||
|
||||
field_type = btf_get_field_type(__btf_name_by_offset(btf, var_type->name_off),
|
||||
field_mask, seen_mask, &align, &sz);
|
||||
if (field_type == 0)
|
||||
return 0;
|
||||
if (field_type < 0)
|
||||
return field_type;
|
||||
|
||||
if (expected_size && expected_size != sz)
|
||||
return 0;
|
||||
if (off % align)
|
||||
return 0;
|
||||
|
||||
switch (field_type) {
|
||||
case BPF_SPIN_LOCK:
|
||||
case BPF_TIMER:
|
||||
case BPF_WORKQUEUE:
|
||||
case BPF_LIST_NODE:
|
||||
case BPF_RB_NODE:
|
||||
case BPF_REFCOUNT:
|
||||
ret = btf_find_struct(btf, var_type, off, sz, field_type,
|
||||
info_cnt ? &info[0] : &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case BPF_KPTR_UNREF:
|
||||
case BPF_KPTR_REF:
|
||||
case BPF_KPTR_PERCPU:
|
||||
ret = btf_find_kptr(btf, var_type, off, sz,
|
||||
info_cnt ? &info[0] : &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case BPF_LIST_HEAD:
|
||||
case BPF_RB_ROOT:
|
||||
ret = btf_find_graph_root(btf, var, var_type,
|
||||
var_idx, off, sz,
|
||||
info_cnt ? &info[0] : &tmp,
|
||||
field_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (ret == BTF_FIELD_IGNORE)
|
||||
return 0;
|
||||
if (!info_cnt)
|
||||
return -E2BIG;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int btf_find_struct_field(const struct btf *btf,
|
||||
const struct btf_type *t, u32 field_mask,
|
||||
struct btf_field_info *info, int info_cnt)
|
||||
{
|
||||
int ret, idx = 0, align, sz, field_type;
|
||||
int ret, idx = 0;
|
||||
const struct btf_member *member;
|
||||
struct btf_field_info tmp;
|
||||
u32 i, off, seen_mask = 0;
|
||||
|
||||
for_each_member(i, t, member) {
|
||||
const struct btf_type *member_type = btf_type_by_id(btf,
|
||||
member->type);
|
||||
|
||||
field_type = btf_get_field_type(__btf_name_by_offset(btf, member_type->name_off),
|
||||
field_mask, &seen_mask, &align, &sz);
|
||||
if (field_type == 0)
|
||||
continue;
|
||||
if (field_type < 0)
|
||||
return field_type;
|
||||
|
||||
off = __btf_member_bit_offset(t, member);
|
||||
if (off % 8)
|
||||
/* valid C code cannot generate such BTF */
|
||||
return -EINVAL;
|
||||
off /= 8;
|
||||
if (off % align)
|
||||
continue;
|
||||
|
||||
switch (field_type) {
|
||||
case BPF_SPIN_LOCK:
|
||||
case BPF_TIMER:
|
||||
case BPF_WORKQUEUE:
|
||||
case BPF_LIST_NODE:
|
||||
case BPF_RB_NODE:
|
||||
case BPF_REFCOUNT:
|
||||
ret = btf_find_struct(btf, member_type, off, sz, field_type,
|
||||
idx < info_cnt ? &info[idx] : &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case BPF_KPTR_UNREF:
|
||||
case BPF_KPTR_REF:
|
||||
case BPF_KPTR_PERCPU:
|
||||
ret = btf_find_kptr(btf, member_type, off, sz,
|
||||
idx < info_cnt ? &info[idx] : &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case BPF_LIST_HEAD:
|
||||
case BPF_RB_ROOT:
|
||||
ret = btf_find_graph_root(btf, t, member_type,
|
||||
i, off, sz,
|
||||
idx < info_cnt ? &info[idx] : &tmp,
|
||||
field_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (ret == BTF_FIELD_IGNORE)
|
||||
continue;
|
||||
if (idx >= info_cnt)
|
||||
return -E2BIG;
|
||||
++idx;
|
||||
ret = btf_find_field_one(btf, t, member_type, i,
|
||||
off, 0,
|
||||
field_mask, &seen_mask,
|
||||
&info[idx], info_cnt - idx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
idx += ret;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
@ -3568,66 +3591,21 @@ static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
|
||||
u32 field_mask, struct btf_field_info *info,
|
||||
int info_cnt)
|
||||
{
|
||||
int ret, idx = 0, align, sz, field_type;
|
||||
int ret, idx = 0;
|
||||
const struct btf_var_secinfo *vsi;
|
||||
struct btf_field_info tmp;
|
||||
u32 i, off, seen_mask = 0;
|
||||
|
||||
for_each_vsi(i, t, vsi) {
|
||||
const struct btf_type *var = btf_type_by_id(btf, vsi->type);
|
||||
const struct btf_type *var_type = btf_type_by_id(btf, var->type);
|
||||
|
||||
field_type = btf_get_field_type(__btf_name_by_offset(btf, var_type->name_off),
|
||||
field_mask, &seen_mask, &align, &sz);
|
||||
if (field_type == 0)
|
||||
continue;
|
||||
if (field_type < 0)
|
||||
return field_type;
|
||||
|
||||
off = vsi->offset;
|
||||
if (vsi->size != sz)
|
||||
continue;
|
||||
if (off % align)
|
||||
continue;
|
||||
|
||||
switch (field_type) {
|
||||
case BPF_SPIN_LOCK:
|
||||
case BPF_TIMER:
|
||||
case BPF_WORKQUEUE:
|
||||
case BPF_LIST_NODE:
|
||||
case BPF_RB_NODE:
|
||||
case BPF_REFCOUNT:
|
||||
ret = btf_find_struct(btf, var_type, off, sz, field_type,
|
||||
idx < info_cnt ? &info[idx] : &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case BPF_KPTR_UNREF:
|
||||
case BPF_KPTR_REF:
|
||||
case BPF_KPTR_PERCPU:
|
||||
ret = btf_find_kptr(btf, var_type, off, sz,
|
||||
idx < info_cnt ? &info[idx] : &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case BPF_LIST_HEAD:
|
||||
case BPF_RB_ROOT:
|
||||
ret = btf_find_graph_root(btf, var, var_type,
|
||||
-1, off, sz,
|
||||
idx < info_cnt ? &info[idx] : &tmp,
|
||||
field_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (ret == BTF_FIELD_IGNORE)
|
||||
continue;
|
||||
if (idx >= info_cnt)
|
||||
return -E2BIG;
|
||||
++idx;
|
||||
ret = btf_find_field_one(btf, var, var_type, -1, off, vsi->size,
|
||||
field_mask, &seen_mask,
|
||||
&info[idx], info_cnt - idx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
idx += ret;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user