[PATCH] libbpf: resolve versioned kfuncs by exact name before essential-name lookup

zhidao su posted 1 patch 6 days, 20 hours ago
tools/lib/bpf/libbpf.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
[PATCH] libbpf: resolve versioned kfuncs by exact name before essential-name lookup
Posted by zhidao su 6 days, 20 hours ago
Some kfuncs use KF_IMPLICIT_ARGS and export both a base name (where
the verifier strips the implicit aux parameter from the prototype) and
a versioned name with additional user-visible parameters (e.g.
scx_bpf_dsq_move_to_local vs scx_bpf_dsq_move_to_local___v2).

When a BPF program declares a weak __ksym with a flavor suffix such as
func___v2, libbpf strips the suffix to obtain the essential name and
looks up the base entry first.  For KF_IMPLICIT_ARGS kfuncs the base
entry has fewer parameters (aux was stripped); the prototype
compatibility check against the versioned declaration (which has the
extra user parameter) then fails, and libbpf leaves the weak symbol
unresolved even though a perfectly-matching versioned kernel entry exists.

Fix by trying an exact-name lookup first when the symbol has an
essential name (i.e. it has a flavor suffix).  If the exact name is
found in kernel BTF and its prototype is compatible, use it directly.
Only fall through to the essential-name lookup when the exact name is
absent or incompatible.

Signed-off-by: zhidao su <suzhidao@xiaomi.com>
---
 tools/lib/bpf/libbpf.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 0be7017800fe..80e495aebe68 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -8630,6 +8630,40 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
 
 	local_func_proto_id = ext->ksym.type_id;
 
+	/*
+	 * For kfuncs with a flavor suffix (e.g. "func___v2"), first try the
+	 * exact name.  If the exact name exists in kernel BTF and its
+	 * prototype is compatible, use it directly.  This is necessary for
+	 * KF_IMPLICIT_ARGS kfuncs that export both a base name (with the
+	 * implicit aux parameter stripped) and a versioned name with extra
+	 * parameters: the essential-name lookup would find the base entry
+	 * (fewer params) and fail the compat check, leaving the weak symbol
+	 * unresolved even though the versioned kernel entry is a perfect
+	 * match.
+	 */
+	if (ext->essent_name) {
+		struct module_btf *exact_mod_btf = NULL;
+		struct btf *exact_btf = NULL;
+		int exact_id;
+
+		exact_id = find_ksym_btf_id(obj, ext->name, BTF_KIND_FUNC,
+					    &exact_btf, &exact_mod_btf);
+		if (exact_id >= 0) {
+			kern_func = btf__type_by_id(exact_btf, exact_id);
+			kfunc_proto_id = kern_func->type;
+			ret = bpf_core_types_are_compat(obj->btf,
+							local_func_proto_id,
+							exact_btf,
+							kfunc_proto_id);
+			if (ret > 0) {
+				kern_btf = exact_btf;
+				mod_btf = exact_mod_btf;
+				kfunc_id = exact_id;
+				goto found;
+			}
+		}
+	}
+
 	kfunc_id = find_ksym_btf_id(obj, ext->essent_name ?: ext->name, BTF_KIND_FUNC, &kern_btf,
 				    &mod_btf);
 	if (kfunc_id < 0) {
@@ -8655,6 +8689,7 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
 		return -EINVAL;
 	}
 
+found:
 	/* set index for module BTF fd in fd_array, if unset */
 	if (mod_btf && !mod_btf->fd_array_idx) {
 		/* insn->off is s16 */
-- 
2.43.0
Re: [PATCH] libbpf: resolve versioned kfuncs by exact name before essential-name lookup
Posted by Andrii Nakryiko 6 days, 19 hours ago
On Thu, Mar 26, 2026 at 1:43 PM zhidao su <soolaugust@gmail.com> wrote:
>
> Some kfuncs use KF_IMPLICIT_ARGS and export both a base name (where
> the verifier strips the implicit aux parameter from the prototype) and
> a versioned name with additional user-visible parameters (e.g.
> scx_bpf_dsq_move_to_local vs scx_bpf_dsq_move_to_local___v2).
>
> When a BPF program declares a weak __ksym with a flavor suffix such as
> func___v2, libbpf strips the suffix to obtain the essential name and
> looks up the base entry first.  For KF_IMPLICIT_ARGS kfuncs the base
> entry has fewer parameters (aux was stripped); the prototype
> compatibility check against the versioned declaration (which has the
> extra user parameter) then fails, and libbpf leaves the weak symbol
> unresolved even though a perfectly-matching versioned kernel entry exists.
>
> Fix by trying an exact-name lookup first when the symbol has an
> essential name (i.e. it has a flavor suffix).  If the exact name is
> found in kernel BTF and its prototype is compatible, use it directly.
> Only fall through to the essential-name lookup when the exact name is
> absent or incompatible.
>
> Signed-off-by: zhidao su <suzhidao@xiaomi.com>
> ---
>  tools/lib/bpf/libbpf.c | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>

libbpf doesn't support (yet) matching triple-underscore-suffixed
kfuncs on the kernel side. We plan to support that, but it should be
done differently.

For now, as a work around, if you need libbpf to match
scx_bpf_dsq_move_to_local___v2, you can add yet another triple
underscore: scx_bpf_dsq_move_to_local___v2___andimeanit

pw-bot: cr


> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 0be7017800fe..80e495aebe68 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -8630,6 +8630,40 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
>
>         local_func_proto_id = ext->ksym.type_id;
>
> +       /*
> +        * For kfuncs with a flavor suffix (e.g. "func___v2"), first try the
> +        * exact name.  If the exact name exists in kernel BTF and its
> +        * prototype is compatible, use it directly.  This is necessary for
> +        * KF_IMPLICIT_ARGS kfuncs that export both a base name (with the
> +        * implicit aux parameter stripped) and a versioned name with extra
> +        * parameters: the essential-name lookup would find the base entry
> +        * (fewer params) and fail the compat check, leaving the weak symbol
> +        * unresolved even though the versioned kernel entry is a perfect
> +        * match.
> +        */
> +       if (ext->essent_name) {
> +               struct module_btf *exact_mod_btf = NULL;
> +               struct btf *exact_btf = NULL;
> +               int exact_id;
> +
> +               exact_id = find_ksym_btf_id(obj, ext->name, BTF_KIND_FUNC,
> +                                           &exact_btf, &exact_mod_btf);
> +               if (exact_id >= 0) {
> +                       kern_func = btf__type_by_id(exact_btf, exact_id);
> +                       kfunc_proto_id = kern_func->type;
> +                       ret = bpf_core_types_are_compat(obj->btf,
> +                                                       local_func_proto_id,
> +                                                       exact_btf,
> +                                                       kfunc_proto_id);
> +                       if (ret > 0) {
> +                               kern_btf = exact_btf;
> +                               mod_btf = exact_mod_btf;
> +                               kfunc_id = exact_id;
> +                               goto found;
> +                       }
> +               }
> +       }
> +
>         kfunc_id = find_ksym_btf_id(obj, ext->essent_name ?: ext->name, BTF_KIND_FUNC, &kern_btf,
>                                     &mod_btf);
>         if (kfunc_id < 0) {
> @@ -8655,6 +8689,7 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
>                 return -EINVAL;
>         }
>
> +found:
>         /* set index for module BTF fd in fd_array, if unset */
>         if (mod_btf && !mod_btf->fd_array_idx) {
>                 /* insn->off is s16 */
> --
> 2.43.0
>
Re: [PATCH] libbpf: resolve versioned kfuncs by exact name before essential-name lookup
Posted by bot+bpf-ci@kernel.org 6 days, 19 hours ago
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 1eaa7527d4da..85268406c0f5 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -8630,6 +8630,40 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
>
>  	local_func_proto_id = ext->ksym.type_id;
>
> +	/*
> +	 * For kfuncs with a flavor suffix (e.g. "func___v2"), first try the
> +	 * exact name.

[ ... ]

> +	if (ext->essent_name) {

This commit fixes a bug introduced by the patch that added
triple-underscore flavor support for kfunc relocation.  Should it
include a Fixes: tag?

Suggested:
Fixes: 5964a223f5e4 ("libbpf: Support triple-underscore flavors for kfunc relocation")

> +		struct module_btf *exact_mod_btf = NULL;

[ ... ]

> +	}
> +


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23617578044