[PATCH] libbpf: load vmlinux BTF in gen_loader mode for struct_ops

From: Siddharth Nayyar

Date: Sun May 24 2026 - 07:26:43 EST


During light skeleton generation (`bpftool gen skeleton -L`), libbpf
runs in gen_loader mode. Previously, `bpf_object__load_vmlinux_btf()`
completely bypassed loading the kernel vmlinux BTF (`obj->btf_vmlinux`)
if `gen_loader` was active.

However, BPF `struct_ops` maps (such as `sched_ext_ops` maps) require
resolving the kernel-side struct type IDs and member sizes at
compile/skeleton generation time. Without loading `btf_vmlinux`, libbpf
cannot query the kernel BTF types, causing light skeleton generation for
`struct_ops` to fail or omit crucial type information.

Fix this by modifying the check to load `btf_vmlinux` even in
`gen_loader` mode if the BPF object actually requires kernel vmlinux BTF
(e.g. contains `struct_ops` maps).

Signed-off-by: Siddharth Nayyar <sidnayyar@xxxxxxxxxx>
---
tools/lib/bpf/libbpf.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 3a80a018fc7d..cb1b7ea884a7 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3590,7 +3590,10 @@ static int bpf_object__load_vmlinux_btf(struct bpf_object *obj, bool force)
int err;

/* btf_vmlinux could be loaded earlier */
- if (obj->btf_vmlinux || obj->gen_loader)
+ if (obj->btf_vmlinux)
+ return 0;
+
+ if (obj->gen_loader && !obj_needs_vmlinux_btf(obj))
return 0;

if (!force && !obj_needs_vmlinux_btf(obj))

---
base-commit: c6e99c10fd9855082568cbd71bb2cc5dc90eda53
change-id: 20260522-libbpf-load-vmlinux-btf-in-gen_loader-mode-4474834aa467

Best regards,
--
Siddharth Nayyar <sidnayyar@xxxxxxxxxx>