From: Samuel Wu <wusamuel@google.com>
To: Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Emil Tsalapatis <emil@etsalapatis.com>,
Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <ndesaulniers@google.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>
Cc: Samuel Wu <wusamuel@google.com>,
kernel-team@android.com, bpf@vger.kernel.org,
linux-kernel@vger.kernel.org, llvm@lists.linux.dev
Subject: [PATCH bpf-next] libbpf: Resolve typeless ksyms in the kernel
Date: Fri, 9 Oct 2026 06:07:08 -0700 [thread overview]
Message-ID: <20261009130708.1370675-1-wusamuel@google.com> (raw)
libbpf resolves typeless symbols by parsing /proc/kallsyms, which
dominates load time for BPF programs with typeless symbols. This mostly
comes from needing to do thousands of syscalls and a linear scan of
kallsyms.
Call bpf_kallsyms_lookup_name() from BPF_PROG_TYPE_SYSCALL, such that
the resolution can be done with a couple of syscalls and a binary
search. This is a similar approach to what the light skeleton does. The
fast path passes the name and result through ctx, which requires commit
ae5ef001aa98 ("bpf: Support variable offsets for syscall PTR_TO_CTX").
Any fast path error (e.g. kernels without ae5ef001aa98) falls back to
the legacy /proc/kallsyms scan, including strong misses, since the
kernel doesn't match LTO "<name>.llvm.<hash>" symbols. Weak misses
default to zero.
Depending on the device, I see ~9-11x loading speedup when resolving a
BPF program with 11 typeless lock externs.
- x86_64 VM, 6.18 + ae5ef001aa98: 147ms -> 17ms
- ARM64 phone, 7.1: 626ms -> 55ms
Signed-off-by: Samuel Wu <wusamuel@google.com>
---
tools/lib/bpf/libbpf.c | 59 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index cb09ded90773..7564ec6bde64 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9590,6 +9590,58 @@ static int bpf_object__read_kallsyms_file(struct bpf_object *obj)
return libbpf_kallsyms_parse(kallsyms_cb, obj);
}
+static int bpf_object__resolve_ksyms_in_kernel(struct bpf_object *obj)
+{
+ struct extern_desc *ext;
+ int i, prog_fd, err = 0;
+ struct {
+ __u64 addr;
+ char name[512];
+ } ctx = {};
+ LIBBPF_OPTS(bpf_prog_load_opts, opts, .prog_flags = BPF_F_SLEEPABLE);
+ LIBBPF_OPTS(bpf_test_run_opts, topts, .ctx_in = &ctx, .ctx_size_in = sizeof(ctx));
+ /* bpf_kallsyms_lookup_name(ctx.name, sizeof(ctx.name), 0, &ctx.addr) */
+ static const struct bpf_insn insns[] = {
+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_1),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
+ BPF_MOV64_IMM(BPF_REG_2, sizeof(ctx.name)),
+ BPF_MOV64_IMM(BPF_REG_3, 0),
+ BPF_EMIT_CALL(BPF_FUNC_kallsyms_lookup_name),
+ BPF_EXIT_INSN(),
+ };
+
+ if (obj->gen_loader || obj->token_fd)
+ return -EOPNOTSUPP;
+
+ prog_fd = bpf_prog_load(BPF_PROG_TYPE_SYSCALL, NULL, "GPL",
+ insns, ARRAY_SIZE(insns), &opts);
+ if (prog_fd < 0)
+ return prog_fd;
+
+ for (i = 0; i < obj->nr_extern; i++) {
+ ext = &obj->externs[i];
+ if (ext->type != EXT_KSYM || ext->ksym.type_id)
+ continue;
+ if (snprintf(ctx.name, sizeof(ctx.name), "%s", ext->name) >= sizeof(ctx.name)) {
+ err = -ENAMETOOLONG;
+ break;
+ }
+ err = bpf_prog_test_run_opts(prog_fd, &topts) ?: (int)topts.retval;
+ if (err == -ENOENT && ext->is_weak) {
+ err = 0;
+ continue;
+ }
+ if (err)
+ break;
+ ext->is_set = true;
+ ext->ksym.addr = ctx.addr;
+ pr_debug("extern (ksym) '%s': resolved in kernel to 0x%llx\n",
+ ext->name, ext->ksym.addr);
+ }
+ close(prog_fd);
+ return err;
+}
+
static int find_ksym_btf_id(struct bpf_object *obj, const char *ksym_name,
__u16 kind, struct btf **res_btf,
struct module_btf **res_mod_btf)
@@ -9863,7 +9915,12 @@ static int bpf_object__resolve_externs(struct bpf_object *obj,
return -EINVAL;
}
if (need_kallsyms) {
- err = bpf_object__read_kallsyms_file(obj);
+ err = bpf_object__resolve_ksyms_in_kernel(obj);
+ if (err) {
+ pr_debug("failed to resolve ksyms in kernel: %s, falling back to /proc/kallsyms\n",
+ errstr(err));
+ err = bpf_object__read_kallsyms_file(obj);
+ }
if (err)
return -EINVAL;
}
--
2.56.0.385.gd3acb90ef8-goog
next reply other threads:[~2026-10-09 13:07 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 13:07 Samuel Wu [this message]
2026-10-09 13:18 ` [PATCH bpf-next] libbpf: Resolve typeless ksyms in the kernel sashiko-bot
2026-10-11 16:06 ` Samuel Wu
2026-10-10 10:09 ` Alan Maguire
2026-10-11 15:56 ` Samuel Wu
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=20261009130708.1370675-1-wusamuel@google.com \
--to=wusamuel@google.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=justinstitt@google.com \
--cc=kernel-team@android.com \
--cc=linux-kernel@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.