Re: [PATCH v2 3/9] bpf/btf: Add a function to search a member of a struct/union
From: Alan Maguire <hidden>
Date: 2023-07-20 22:35:03
Also in:
bpf, lkml
On 17/07/2023 16:23, Masami Hiramatsu (Google) wrote:
From: Masami Hiramatsu (Google) <mhiramat@kernel.org> Add btf_find_struct_member() API to search a member of a given data structure or union from the member's name. Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
A few small things below, but Reviewed-by: Alan Maguire <redacted>
quoted hunk ↗ jump to hunk
--- include/linux/btf.h | 3 +++ kernel/bpf/btf.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+)diff --git a/include/linux/btf.h b/include/linux/btf.h index 98fbbcdd72ec..097fe9b51562 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h@@ -225,6 +225,9 @@ const struct btf_type *btf_find_func_proto(struct btf *btf, const char *func_name); const struct btf_param *btf_get_func_param(const struct btf_type *func_proto, s32 *nr); +const struct btf_member *btf_find_struct_member(struct btf *btf, + const struct btf_type *type, + const char *member_name); #define for_each_member(i, struct_type, member) \ for (i = 0, member = btf_type_member(struct_type); \diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index e015b52956cb..452ffb0393d6 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c@@ -1992,6 +1992,44 @@ const struct btf_param *btf_get_func_param(const struct btf_type *func_proto, s3 return NULL; } +/* + * Find a member of data structure/union by name and return it. + * Return NULL if not found, or -EINVAL if parameter is invalid. + */ +const struct btf_member *btf_find_struct_member(struct btf *btf, + const struct btf_type *type, + const char *member_name) +{ + const struct btf_member *members, *ret; + const char *name; + int i, vlen; + + if (!btf || !member_name || !btf_type_is_struct(type)) + return ERR_PTR(-EINVAL); + + vlen = btf_type_vlen(type); + members = (const struct btf_member *)(type + 1); + + for (i = 0; i < vlen; i++) {
could use for_each_member() here I think, or perhaps use btf_type_member(type) when getting member pointer above.
+ if (!members[i].name_off) {
+ /* unnamed union: dig deeper */
+ type = btf_type_by_id(btf, members[i].type);
+ if (!IS_ERR_OR_NULL(type)) {
+ ret = btf_find_struct_member(btf, type,
+ member_name);You'll need to skip modifiers before calling btf_find_struct_member() here I think; it's possible to have a const anonymous union for example, so to get to the union you'd need to skip the modifiers first. Otherwise you could fail the btf_type_is_struct() test on re-entry.
+ if (!IS_ERR_OR_NULL(ret))
+ return ret;
+ }
+ } else {
+ name = btf_name_by_offset(btf, members[i].name_off);
+ if (name && !strcmp(member_name, name))
+ return &members[i];
+ }
+ }
+
+ return NULL;
+}
+
static u32 btf_resolved_type_id(const struct btf *btf, u32 type_id)
{
while (type_id < btf->start_id)