From: Ihor Solodrai <ihor.solodrai@linux.dev>
To: dwarves@vger.kernel.org, alan.maguire@oracle.com, acme@kernel.org
Cc: bpf@vger.kernel.org, andrii@kernel.org, ast@kernel.org,
eddyz87@gmail.com, tj@kernel.org, kernel-team@meta.com
Subject: [PATCH dwarves v1 3/3] btf_encoder: support kfuncs with KF_MAGIC_ARGS flag
Date: Wed, 29 Oct 2025 12:02:49 -0700 [thread overview]
Message-ID: <20251029190249.3323752-4-ihor.solodrai@linux.dev> (raw)
In-Reply-To: <20251029190249.3323752-1-ihor.solodrai@linux.dev>
For BPF kernel functions marked with KF_MAGIC_ARGS flag we emit two
functions to BTF:
* kfunc_impl() with prototype that matches kernel declaration
* kfunc() with prototype that omits __magic arguments
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
btf_encoder.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 119 insertions(+), 2 deletions(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index b730280..7a10be3 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -48,6 +48,7 @@
#define KF_ARENA_RET (1 << 13)
#define KF_ARENA_ARG1 (1 << 14)
#define KF_ARENA_ARG2 (1 << 15)
+#define KF_MAGIC_ARGS (1 << 16)
struct btf_id_and_flag {
uint32_t id;
@@ -1404,8 +1405,8 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
return btf_fn_id;
}
-static int btf_encoder__add_bpf_kfunc(struct btf_encoder *encoder,
- struct btf_encoder_func_state *state)
+static int btf_encoder__add_bpf_kfunc_instance(struct btf_encoder *encoder,
+ struct btf_encoder_func_state *state)
{
int btf_fn_id, err;
@@ -1426,6 +1427,122 @@ static int btf_encoder__add_bpf_kfunc(struct btf_encoder *encoder,
return 0;
}
+static inline bool str_ends_with(const char *str, const char *suffix)
+{
+ int suffix_len = strlen(suffix);
+ int str_len = strlen(str);
+
+ if (str_len < suffix_len)
+ return false;
+
+ return strcmp(str + str_len - suffix_len, suffix) == 0;
+}
+
+#define BPF_KF_IMPL_SUFFIX "_impl"
+#define BPF_KF_ARG_MAGIC_SUFFIX "__magic"
+
+static inline bool btf__is_kf_magic_arg(const struct btf *btf, const struct btf_encoder_func_parm *p)
+{
+ const char *name;
+
+ name = btf__name_by_offset(btf, p->name_off);
+ if (!name)
+ return false;
+
+ return str_ends_with(name, BPF_KF_ARG_MAGIC_SUFFIX);
+}
+
+/*
+ * A kfunc with KF_MAGIC_ARGS flag has some number of arguments set implicitly by the BPF
+ * verifier. Such arguments are identified by __magic suffix in the argument name.
+ * process_kfunc_magic_args() checks the arguments from last to first, and returns the number of
+ * magic arguments. Note that *all* magic arguments must come after *all* normal arguments in the
+ * function signature. If this assumption is violated, or if no __magic arguments are found,
+ * process_kfunc_magic_args() returns an error.
+ */
+static int process_kfunc_magic_args(struct btf_encoder_func_state *state)
+{
+ const struct btf *btf = state->encoder->btf;
+ const struct btf_encoder_func_parm *p;
+ int cnt = 0, i;
+
+ for (i = state->nr_parms - 1; i >= 0; i--) {
+ p = &state->parms[i];
+ if (btf__is_kf_magic_arg(btf, p)) {
+ cnt++;
+ if (cnt != state->nr_parms - i)
+ goto out_err;
+ } else if (cnt == 0) {
+ goto out_err;
+ }
+ }
+
+ return cnt;
+
+out_err:
+ btf__log_err(btf, BTF_KIND_FUNC_PROTO, state->elf->name, true, 0,
+ "return=%u Error emitting BTF func proto for KF_MAGIC_ARGS kfunc: unexpected kfunc signature",
+ p->type_id);
+ return -1;
+}
+
+/*
+ * For KF_MAGIC_ARGS kfuncs we emit two BTF functions (and protos):
+ * - bpf_foo_impl(<original kernel args>)
+ * - bpf_foo(<bpf args w/o magic args>)
+ * We achieve this by creating a temporary btf_encoder_func_state-s
+ */
+static int btf_encoder__add_bpf_kfunc_with_magic_args(struct btf_encoder *encoder,
+ struct btf_encoder_func_state *state)
+{
+ struct btf_encoder_func_annot tmp_annots[state->nr_annots];
+ struct btf_encoder_func_state tmp_state = *state;
+ struct elf_function tmp_elf = *state->elf;
+ char tmp_name[KSYM_NAME_LEN];
+ int err, i, j, nr_magic_args;
+
+ /* First, add kfunc_impl(), modifying only the name */
+ strcpy(tmp_name, state->elf->name);
+ strcat(tmp_name, BPF_KF_IMPL_SUFFIX);
+ tmp_elf.name = tmp_name;
+ tmp_state.elf = &tmp_elf;
+ err = btf_encoder__add_bpf_kfunc_instance(encoder, &tmp_state);
+ if (err < 0)
+ return -1;
+
+ /* Then add kfunc() with omitted magic arguments */
+ nr_magic_args = process_kfunc_magic_args(state);
+ if (nr_magic_args <= 0)
+ return -1;
+
+ tmp_state.elf = state->elf;
+ tmp_state.nr_parms -= nr_magic_args;
+ j = 0;
+ for (i = 0; i < state->nr_annots; i++) {
+ if (state->annots[i].component_idx < tmp_state.nr_parms)
+ tmp_annots[j++] = state->annots[i];
+ }
+ tmp_state.nr_annots = j;
+ tmp_state.annots = tmp_annots;
+ err = btf_encoder__add_bpf_kfunc_instance(encoder, &tmp_state);
+ if (err < 0)
+ return -1;
+
+ return 0;
+}
+
+static inline int btf_encoder__add_bpf_kfunc(struct btf_encoder *encoder,
+ struct btf_encoder_func_state *state)
+{
+ uint32_t flags = state->elf->kfunc_flags;
+
+ if (KF_MAGIC_ARGS & flags)
+ return btf_encoder__add_bpf_kfunc_with_magic_args(encoder, state);
+
+ return btf_encoder__add_bpf_kfunc_instance(encoder, state);
+}
+
+
static int elf_function__name_cmp(const void *_a, const void *_b)
{
const struct elf_function *a = _a;
--
2.51.1
next prev parent reply other threads:[~2025-10-29 19:03 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-29 19:02 [PATCH dwarves v1 0/3] btf_encoder: support for BPF magic kernel functions Ihor Solodrai
2025-10-29 19:02 ` [PATCH dwarves v1 1/3] btf_encoder: refactor btf_encoder__add_func_proto Ihor Solodrai
2025-10-30 0:34 ` Eduard Zingerman
2025-10-29 19:02 ` [PATCH dwarves v1 2/3] btf_encoder: factor out btf_encoder__add_bpf_kfunc() Ihor Solodrai
2025-10-29 19:02 ` Ihor Solodrai [this message]
2025-11-04 20:59 ` [PATCH dwarves v1 0/3] btf_encoder: support for BPF magic kernel functions Alan Maguire
2025-11-04 22:25 ` Ihor Solodrai
2025-11-04 22:33 ` Eduard Zingerman
2025-11-04 22:37 ` Ihor Solodrai
2025-11-14 18:33 ` Alan Maguire
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251029190249.3323752-4-ihor.solodrai@linux.dev \
--to=ihor.solodrai@linux.dev \
--cc=acme@kernel.org \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=eddyz87@gmail.com \
--cc=kernel-team@meta.com \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox