On Wed, Feb 21, 2024 at 1:18 AM Jiri Olsa <olsajiri@xxxxxxxxx> wrote: > > On Tue, Feb 20, 2024 at 11:51:01AM +0800, Menglong Dong wrote: > > SNIP > > > +static int get_ctx_arg_idx_aligned(struct btf *btf, const struct btf_type *t, > > + int off) > > +{ > > + const struct btf_param *args; > > + u32 offset = 0, nr_args; > > + int i; > > + > > + nr_args = btf_type_vlen(t); > > + args = (const struct btf_param *)(t + 1); > > + for (i = 0; i < nr_args; i++) { > > + if (offset == off) > > + return i; > > + > > + t = btf_type_skip_modifiers(btf, args[i].type, NULL); > > + offset += btf_type_is_ptr(t) ? 8 : roundup(t->size, 8); > > + if (offset > off) > > + return -1; > > + } > > + return -1; > > +} > > + > > +/* This function is similar to btf_check_func_type_match(), except that it > > + * only compare some function args of the function prototype t1 and t2. > > + */ > > could we reuse btf_check_func_type_match instead? perhaps just > adding extra argument with arguments bitmap to it? > This is a little difficult, as the way we check the consistency of t1 and t2 is a little different. in btf_check_func_type_match(), we check the args of t1 and t2 by index. But in btf_check_func_part_match(), we check the args of t1 and t2 by offset. Reusing can make btf_check_func_type_match become complex and hard to understand. Anyway, let me have a try to see if it works to reuse btf_check_func_type_match(). Thanks! Menglong Dong > jirka > > > +int btf_check_func_part_match(struct btf *btf1, const struct btf_type *func1, > > + struct btf *btf2, const struct btf_type *func2, > > + u64 func_args) > > +{ > > + const struct btf_param *args1, *args2; > > + u32 nargs1, i, offset = 0; > > + const char *s1, *s2; > > + > > + if (!btf_type_is_func_proto(func1) || !btf_type_is_func_proto(func2)) > > + return -EINVAL; > > + > > + args1 = (const struct btf_param *)(func1 + 1); > > + args2 = (const struct btf_param *)(func2 + 1); > > + nargs1 = btf_type_vlen(func1); > > + > > + for (i = 0; i <= nargs1; i++) { > > + const struct btf_type *t1, *t2; > > + > > + if (!(func_args & (1 << i))) > > + goto next; > > + > > + if (i < nargs1) { > > + int t2_index; > > + > > + /* get the index of the arg corresponding to args1[i] > > + * by the offset. > > + */ > > + t2_index = get_ctx_arg_idx_aligned(btf2, func2, > > + offset); > > + if (t2_index < 0) > > + return -EINVAL; > > + > > + t1 = btf_type_skip_modifiers(btf1, args1[i].type, NULL); > > + t2 = btf_type_skip_modifiers(btf2, args2[t2_index].type, > > + NULL); > > + } else { > > + /* i == nargs1, this is the index of return value of t1 */ > > + if (get_ctx_arg_total_size(btf1, func1) != > > + get_ctx_arg_total_size(btf2, func2)) > > + return -EINVAL; > > + > > + /* check the return type of t1 and t2 */ > > + t1 = btf_type_skip_modifiers(btf1, func1->type, NULL); > > + t2 = btf_type_skip_modifiers(btf2, func2->type, NULL); > > + } > > + > > + if (t1->info != t2->info || > > + (btf_type_has_size(t1) && t1->size != t2->size)) > > + return -EINVAL; > > + if (btf_type_is_int(t1) || btf_is_any_enum(t1)) > > + goto next; > > + > > + if (btf_type_is_struct(t1)) > > + goto on_struct; > > + > > + if (!btf_type_is_ptr(t1)) > > + return -EINVAL; > > + > > + t1 = btf_type_skip_modifiers(btf1, t1->type, NULL); > > + t2 = btf_type_skip_modifiers(btf2, t2->type, NULL); > > + if (!btf_type_is_struct(t1) || !btf_type_is_struct(t2)) > > + return -EINVAL; > > + > > +on_struct: > > + s1 = btf_name_by_offset(btf1, t1->name_off); > > + s2 = btf_name_by_offset(btf2, t2->name_off); > > + if (strcmp(s1, s2)) > > + return -EINVAL; > > +next: > > + if (i < nargs1) { > > + t1 = btf_type_skip_modifiers(btf1, args1[i].type, NULL); > > + offset += btf_type_is_ptr(t1) ? 8 : roundup(t1->size, 8); > > + } > > + } > > + > > + return 0; > > +} > > + > > static bool btf_is_dynptr_ptr(const struct btf *btf, const struct btf_type *t) > > { > > const char *name; > > -- > > 2.39.2 > >