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 <[email protected]>
---
 tools/lib/bpf/libbpf.c          | 54 +++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf_internal.h |  1 +
 2 files changed, 55 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 64c1ab005e6d..084699448a94 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -12275,6 +12275,60 @@ 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;
+       }
+}
+
+bool btf_type_is_traceable_func(const struct btf *btf, const struct btf_type 
*t)
+{
+       const struct btf_type *proto;
+       const struct btf_param *args;
+       __u32 i, nargs;
+       __s64 ret;
+
+       proto = btf_type_by_id(btf, t->type);
+       if (BTF_INFO_KIND(proto->info) != BTF_KIND_FUNC_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/union return argument type. */
+       t = btf__type_by_id(btf, proto->type);
+       while (t && btf_type_is_modifier(t))
+               t = btf__type_by_id(btf, t->type);
+
+       if (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;
+
+               /* No support of struct argument size greater than 16 bytes. */
+               ret = btf__resolve_size(btf, args[i].type);
+               if (ret < 0 || ret > 16)
+                       return false;
+       }
+
+       return true;
+}
+
 static inline int add_uprobe_event_legacy(const char *probe_name, bool 
retprobe,
                                          const char *binary_path, size_t 
offset)
 {
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index 4bcb6ca69bb1..1b539c901898 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -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)
 {
-- 
2.53.0


Reply via email to