diff --git a/src/btfparse.c b/src/btfparse.c index edf004b2ebc35d0c2d492b1e4744c45ba3e9445d..c52b3779230d14a5137af821aca99514551d9dcf 100644 --- a/src/btfparse.c +++ b/src/btfparse.c @@ -195,21 +195,24 @@ free_ma: return NULL; } -int btf_type_find_struct(struct btf *btf, char *name) { +int btf_type_find_struct(struct btf *btf, char *name) +{ return btf__find_by_name_kind(btf, name, BTF_KIND_STRUCT); } -int btf_type_struct_size(struct btf *btf, char *name) { +int btf_type_struct_size(struct btf *btf, char *name) +{ int typeid = btf_type_find_struct(btf, name); if (typeid < 0) return typeid; - + return btf__resolve_size(btf, typeid); } int btf_type_size(struct btf *btf, char *typename) { - if (strncmp(typename, "struct", strlen("struct")) == 0) { + if (strncmp(typename, "struct", strlen("struct")) == 0) + { return btf_type_struct_size(btf, &typename[strlen("struct ")]); } return -ENOTSUP; @@ -217,31 +220,43 @@ int btf_type_size(struct btf *btf, char *typename) int btf_type_by_name(struct btf *btf, char *name) { - if (strncmp(name, "struct", strlen("struct")) == 0) { + if (strncmp(name, "struct", strlen("struct")) == 0) + { return btf_type_find_struct(btf, &name[strlen("struct ")]); } return -ENOTSUP; } -int btf_get_member_offset(struct btf *btf, char *name, char *member_name) +int __btf_get_member_offset(struct btf *btf, int typeid, char *member_name) { - int typeid = btf_type_by_name(btf, name); const struct btf_type *t; - const struct btf_member *m; const char *tmp_member_name; + const struct btf_member *m; int i; - - if (typeid < 0) - return typeid; - + t = btf__type_by_id(btf, typeid); m = btf_members(t); for (i = 0; i < btf_vlen(t); i++, m++) { + if (m->name_off == 0) + { + int tmp_offset = __btf_get_member_offset(btf, m->type, member_name); + if (tmp_offset >= 0) // find it + return m->offset + tmp_offset; + } tmp_member_name = btf__name_by_offset(btf, m->name_off); if (tmp_member_name && tmp_member_name[0] && strcmp(tmp_member_name, member_name) == 0) return m->offset; } - return -ENOENT; } + +int btf_get_member_offset(struct btf *btf, char *name, char *member_name) +{ + int typeid = btf_type_by_name(btf, name); + + if (typeid < 0) + return typeid; + + return __btf_get_member_offset(btf, typeid, member_name); +} diff --git a/tests/bpf/bpf_core.bpf.c b/tests/bpf/bpf_core.bpf.c index 908845290bf44098f464884f482a0ea03fb7355a..47dfc2600abcdedef789a46588de02c1495e5ae2 100644 --- a/tests/bpf/bpf_core.bpf.c +++ b/tests/bpf/bpf_core.bpf.c @@ -7,7 +7,7 @@ SEC("kprobe/tcp_sendmsg") -int BPF_KPROBE(tcp_sendmsg, u64 sk) { +int BPF_KPROBE(tcp_sendmsg, struct sock *sk) { // doesn't matter if parameter is 'struct task_struct *' type, we just check if compilation is ok. bpf_core_task_struct_thread_info_exist(sk); return 0; diff --git a/tests/testbtfparse.c b/tests/testbtfparse.c index e697f64a1747c33a7f6038e2ce8d0a4d0bd0e8ee..52dfa9d179f777096ef6500c4d2ad30986ff0510 100644 --- a/tests/testbtfparse.c +++ b/tests/testbtfparse.c @@ -30,4 +30,12 @@ Test(btfparse, btf_get_member_offset) struct btf *btf = btf_load(NULL); cr_assert_eq(btf_get_member_offset(btf, "struct sock", "__sk_common"), 0); cr_assert_gt(btf_get_member_offset(btf, "struct sock", "sk_sndbuf"), 0); +} + + +Test(btfparse, btf_get_member_offset_union) +{ + struct btf *btf = btf_load(NULL); + cr_assert_gt(btf_get_member_offset(btf, "struct page", "mapping"), 0); + cr_assert_gt(btf_get_member_offset(btf, "struct kernfs_node", "name"), 0); } \ No newline at end of file