Skip to content

Commit

Permalink
libbpf: Allow kernel_struct_has_field to reach field in unnamed struc…
Browse files Browse the repository at this point in the history
…t or union

Some fields can belong to unnamed struct or union (e.g. rcu and
rcu_users fields of task_struct). In C, they are accessed as if their
belong directly to the parent of the unnamed struct or union but this
is not the case for BTF.

When looking for a field, kernel_struct_has_field should also look
reccursively into unnamed structs or unions. That allows code such as
the following to work as expected:

BPF.kernel_struct_has_field('task_struct', 'rcu')

Signed-off-by: Jerome Marchand <[email protected]>
  • Loading branch information
jeromemarchand authored and chenhengqi committed Nov 2, 2022
1 parent 917b97b commit aee989c
Showing 1 changed file with 18 additions and 10 deletions.
28 changes: 18 additions & 10 deletions src/cc/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1393,12 +1393,27 @@ bool bpf_has_kernel_btf(void)
return true;
}

static int find_member_by_name(struct btf *btf, const struct btf_type *btf_type, const char *field_name) {
const struct btf_member *btf_member = btf_members(btf_type);
int i;

for (i = 0; i < btf_vlen(btf_type); i++, btf_member++) {
const char *name = btf__name_by_offset(btf, btf_member->name_off);
if (!strcmp(name, field_name)) {
return 1;
} else if (name[0] == '\0') {
if (find_member_by_name(btf, btf__type_by_id(btf, btf_member->type), field_name))
return 1;
}
}
return 0;
}

int kernel_struct_has_field(const char *struct_name, const char *field_name)
{
const struct btf_type *btf_type;
const struct btf_member *btf_member;
struct btf *btf;
int i, ret, btf_id;
int ret, btf_id;

btf = btf__load_vmlinux_btf();
ret = libbpf_get_error(btf);
Expand All @@ -1412,14 +1427,7 @@ int kernel_struct_has_field(const char *struct_name, const char *field_name)
}

btf_type = btf__type_by_id(btf, btf_id);
btf_member = btf_members(btf_type);
for (i = 0; i < btf_vlen(btf_type); i++, btf_member++) {
if (!strcmp(btf__name_by_offset(btf, btf_member->name_off), field_name)) {
ret = 1;
goto cleanup;
}
}
ret = 0;
ret = find_member_by_name(btf, btf_type, field_name);

cleanup:
btf__free(btf);
Expand Down

0 comments on commit aee989c

Please sign in to comment.