There isn't currently a convenience function to check if a particular kernel version is running similar to bpf_core_field_exists. There can be cases where based on the actual kernel being run different kprobes has to be used when tracing the kernel. One example is the change introduced in 4c5b47997521 ("vfs: add fileattr ops"). Before this commit if one wants to trace fileattr changes this has to be done by a distinct kprobe on every filesystem as there was no common code where fileattr changes when through. Post this commit this can be performed by a single kprobe on the common vfs_fileattr_set function. To accommodate such use cases simply add a libbpf api btf__field_exists which can be used to check for the running kernel version and act appropriately. Signed-off-by: Nikolay Borisov <nborisov@xxxxxxxx> --- tools/lib/bpf/btf.c | 28 ++++++++++++++++++++++++++++ tools/lib/bpf/btf.h | 2 ++ tools/lib/bpf/libbpf.map | 1 + 3 files changed, 31 insertions(+) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 9aa19c89f758..890a2071bd00 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -697,6 +697,34 @@ int btf__resolve_type(const struct btf *btf, __u32 type_id) return type_id; } +bool btf__field_exists(const struct btf *btf, const char *struct_name, + const char *field_name) +{ + const struct btf_type *t; + struct btf_member *m; + int i; + __s32 type_id = btf__find_by_name(btf, struct_name); + + if (type_id < 0) + return false; + + t = btf__type_by_id(btf, type_id); + if (!t) + return false; + + if (!btf_is_composite(t)) + return false; + + for_each_member(i, t, m) { + const char *n = btf__name_by_offset(btf, m->name_off); + + if (strcmp(n, field_name) == 0) + return true; + } + + return false; +} + __s32 btf__find_by_name(const struct btf *btf, const char *type_name) { __u32 i, nr_types = btf__type_cnt(btf); diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h index 74039f8afc63..1eb8d840b46b 100644 --- a/tools/lib/bpf/btf.h +++ b/tools/lib/bpf/btf.h @@ -144,6 +144,8 @@ LIBBPF_API enum btf_endianness btf__endianness(const struct btf *btf); LIBBPF_API int btf__set_endianness(struct btf *btf, enum btf_endianness endian); LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id); LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id); +LIBBPF_API bool btf__field_exists(const struct btf *btf, const char *struct_name, + const char *field_name); LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id); LIBBPF_API int btf__fd(const struct btf *btf); LIBBPF_API void btf__set_fd(struct btf *btf, int fd); diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 529783967793..9a0d50604cca 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -427,6 +427,7 @@ LIBBPF_0.7.0 { bpf_program__log_level; bpf_program__set_log_buf; bpf_program__set_log_level; + btf__field_exists; libbpf_probe_bpf_helper; libbpf_probe_bpf_map_type; libbpf_probe_bpf_prog_type; -- 2.25.1