libbpf: Add btf_type_is_traceable_func function

Adding btf_type_is_traceable_func function to perform same checks
as the kernel's btf_distill_func_proto function to prevent attachment
on some of the functions.

Exporting the function via libbpf_internal.h because it will be used
by benchmark test in following changes.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20260606123955.345967-20-jolsa@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Jiri Olsa 2026-06-06 14:39:44 +02:00 committed by Alexei Starovoitov
parent 630e85a9f0
commit 616a93b473
2 changed files with 80 additions and 0 deletions

View File

@ -12450,6 +12450,85 @@ static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, stru
return ret;
}
#define MAX_BPF_FUNC_ARGS 12
static bool btf_type_is_modifier(const struct btf_type *t)
{
switch (BTF_INFO_KIND(t->info)) {
case BTF_KIND_TYPEDEF:
case BTF_KIND_VOLATILE:
case BTF_KIND_CONST:
case BTF_KIND_RESTRICT:
case BTF_KIND_TYPE_TAG:
return true;
default:
return false;
}
}
#define MAX_RESOLVE_DEPTH 32
static int btf_get_type_size(const struct btf *btf, __u32 type_id,
const struct btf_type **ret_type)
{
const struct btf_type *t;
int i;
*ret_type = btf__type_by_id(btf, 0);
if (!type_id)
return 0;
t = btf__type_by_id(btf, type_id);
for (i = 0; i < MAX_RESOLVE_DEPTH && t && btf_type_is_modifier(t); i++)
t = btf__type_by_id(btf, t->type);
if (!t || i == MAX_RESOLVE_DEPTH)
return -EINVAL;
*ret_type = t;
if (btf_is_ptr(t))
return btf__pointer_size(btf);
if (btf_is_int(t) || btf_is_any_enum(t) || btf_is_struct(t) || btf_is_union(t))
return t->size;
return -EINVAL;
}
bool btf_type_is_traceable_func(const struct btf *btf, const struct btf_type *t)
{
const struct btf_param *args;
const struct btf_type *proto;
__u32 i, nargs;
int ret;
if (!btf_is_func(t))
return false;
proto = btf__type_by_id(btf, t->type);
if (!proto || !btf_is_func_proto(proto))
return false;
args = (const struct btf_param *)(proto + 1);
nargs = btf_vlen(proto);
if (nargs > MAX_BPF_FUNC_ARGS)
return false;
/* No support for struct return type. */
ret = btf_get_type_size(btf, proto->type, &t);
if (ret < 0 || btf_is_struct(t) || btf_is_union(t))
return false;
for (i = 0; i < nargs; i++) {
/* No support for variable args. */
if (i == nargs - 1 && args[i].type == 0)
return false;
ret = btf_get_type_size(btf, args[i].type, &t);
/* No support of struct argument size greater than 16 bytes. */
if (ret < 0 || ret > 16)
return false;
/* No support for void argument. */
if (ret == 0)
return false;
}
return true;
}
static inline int add_uprobe_event_legacy(const char *probe_name, bool retprobe,
const char *binary_path, size_t offset)
{

View File

@ -250,6 +250,7 @@ const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, _
const struct btf_header *btf_header(const struct btf *btf);
void btf_set_base_btf(struct btf *btf, const struct btf *base_btf);
int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map);
bool btf_type_is_traceable_func(const struct btf *btf, const struct btf_type *t);
static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t)
{