This way we can have trampoline on function that has arguments with types like: kuid_t uid kgid_t gid which unwind into small structs like: typedef struct { uid_t val; } kuid_t; typedef struct { gid_t val; } kgid_t; And we can use them in bpftrace like: (assuming d_path changes are in) # bpftrace -e 'lsm:path_chown { printf("uid %d, gid %d\n", args->uid, args->gid) }' Attaching 1 probe... uid 0, gid 0 uid 1000, gid 1000 ... Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx> --- kernel/bpf/btf.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 58c9af1d4808..f8fee5833684 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -362,6 +362,14 @@ static bool btf_type_is_struct(const struct btf_type *t) return kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION; } +/* type is struct and its size is within 8 bytes + * and it can be value of function argument + */ +static bool btf_type_is_struct_arg(const struct btf_type *t) +{ + return btf_type_is_struct(t) && (t->size <= sizeof(u64)); +} + static bool __btf_type_is_struct(const struct btf_type *t) { return BTF_INFO_KIND(t->info) == BTF_KIND_STRUCT; @@ -3768,7 +3776,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, /* skip modifiers */ while (btf_type_is_modifier(t)) t = btf_type_by_id(btf, t->type); - if (btf_type_is_int(t) || btf_type_is_enum(t)) + if (btf_type_is_int(t) || btf_type_is_enum(t) || btf_type_is_struct_arg(t)) /* accessing a scalar */ return true; if (!btf_type_is_ptr(t)) { @@ -4161,6 +4169,8 @@ static int __get_type_size(struct btf *btf, u32 btf_id, return sizeof(void *); if (btf_type_is_int(t) || btf_type_is_enum(t)) return t->size; + if (btf_type_is_struct_arg(t)) + return t->size; *bad_type = t; return -EINVAL; } -- 2.25.4