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)
{