How to Find Supported eBPF Helper Functions for Any Kernel & Program Type
Three practical methods—bpftool, eBPF Docs, and a kernel-source deep-dive—to verify which helpers your eBPF program can really use.
When developing eBPF programs, the eBPF features available to you depend heavily on where your code will run.
And beyond the kernel version itself, it's important to consider the specific eBPF helper functions supported, as these vary based on both the kernel version and the type of program you're developing.
In today’s newsletter, we look at practical ways to answer a common question:
“Can I use eBPF helper function abc
in a xyz
program on kernel version n
?”
🚀 Special thanks to Patrick Pichler, Engineer at Miggo, for putting together this practical guest post for eBPFChirp!
Using bpftool
If you’ve ever written any eBPF programs before, chances are you’ve already come across bpftool.
Anyways, bpftool—part of the libbpf project—is used to list all loaded eBPF programs and maps, inspect specific map contents, and even dump BTF information from binaries.
One particularly useful feature I only discovered recently is the bpftool feature probe kernel
command.
It outputs a detailed list of all supported program types, map types, and available helpers—organized by program type—for your current kernel version.
For example, suppose you want to check if syscall
-type eBPF programs support the bpf_spin_lock
helper on your system. Just run:
Under section labeled "eBPF helpers supported for program type syscall" if helper named bpf_spin_lock
appears there, it means the helper is supported on your current kernel. If it’s missing, it’s not.
That said, the bpftool
approach does have a few limitations.
The most important one is that it only reflects the features of the currently running kernel.
There’s just no built-in way to check if a specific helper is supported in another kernel version—you’d have to run that version locally to find out.
Another issue I’ve run into (and haven’t fully figured out yet) is that bpftool
occasionally fails to determine helper support for certain program types.
For those cases, you might see a message like:
eBPF helpers supported for program type tracing: Could not determine which helpers are available
I still really like the bpftool
approach—it’s fast, local, and saves me from scrolling through online documentation.
But there are other ways to check as well.
Using eBPF Docs
One pretty amazing resource for anything eBPF related is eBPF Docs.
And it not only documents most eBPF helpers, program types, and map definitions—but also specifies the kernel version in which each feature was introduced.
For example, the bpf_spin_lock
helper is documented under linux/helper-function/bpf_spin_lock/.
The first thing you’ll notice on the page is the kernel version the helper was introduced in—For instance, bpf_spin_lock
was added in v5.1.
You’ll also find a concise overview of what the helper does, how to use it, and—most importantly—a list of program types it's available in.
However, there’s one downside: the website documentation is manually maintained, so it may occasionally contain errors or missing information.
Nonetheless, when a helper becomes available for a specific program type only after its initial introduction in a particular kernel version, you'll typically see a small kernel version label next to that program type, indicating when support was added.
While this isn’t shown for the bpf_spin_lock
helper, we can observe it clearly with the bpf_sk_storage_get
helper, where you'll find such a label next to BPF_PROG_TYPE_TRACING
.
If you spot any missing information or errors on the page, consider heading over to the documentation’s GitHub repository and opening a pull request with a fix.
The maintainers are friendly, and contributions are very much welcome.
Using Bootlin Website (aka exploring Linux Kernel Source Code)
As we’ve seen, both bpftool
and eBPF Docs have their limitations when it comes to figuring out which helpers are available for specific eBPF program types across different kernel versions.
If neither of these approaches help, the most reliable—though also the most involved—option is to examine the Linux kernel source code directly for the kernel version you're targeting.
Let’s walk through an example.
Say we want to check if the bpf_spin_lock
helper is available in BPF_PROG_TYPE_TRACING
programs on Linux kernel version v5.10.
Start by navigating to the include/linux/bpf_types.h file for kernel version v5.10.
This file defines all the eBPF program types supported in that particular kernel release.
💡 The eBPF verifier also uses this file to map each program type to a set of verifier options, based on macro definitions found in bpf_types.h header.
Now we know this eBPF program type is available, but to check which helper functions it supports, you need to find the verifier's corresponding operations structure in the Linux kernel source code.
In other words, we need to find a structure with the operations, that the eBPF verifier allow for this type of eBPF program.
Luckily, these verifier operations structures follow a consistent naming pattern.
They're typically defined by taking the second argument given to the BPF_PROG_TYPE()
macro (as in the image above) and adding the suffix _verifier_ops
.
Meaning, if the second argument to the BPF_PROG_TYPE()
macro is tracing
, the corresponding verifier operations structure will be named tracing_verifier_ops
as you’ll see below.
Searching for the tracing_verifier_ops
symbol (in the Search Identifier gray box on top right corner), you’ll find:
Specifically, look at the structure's get_func_proto
function pointer—this is where the allowed helper functions are defined for each program type.
And the logic inside tracing_prog_func_proto
is fairly straightforward.
It primarily consists of a series of switch
statements that match the requested helper's bpf_func_id
.
If a match is found, the function returns a pointer to the helper’s definition; otherwise, it returns NULL
.
Since bpf_spin_lock
isn’t listed in the switch
statement of tracing_prog_func_proto
, we follow the function call in the default
branch of the switch statement.
Continue tracing down the chain until we either find the helper ID we’re looking for or reach a point where NULL
is returned.
In our case, bpf_spin_lock
never appears, and eventually NULL
is returned—meaning bpf_spin_lock
is not supported in BPF_PROG_TYPE_TRACING
on Linux kernel v5.10.
But wait—according to eBPF Docs, tracing
is listed as a program type that supports bpf_spin_lock
. So where is that information coming from?
To clarify this discrepancy, if you repeat the same verification steps using Linux kernel version 5.15—the next LTS (Long-Term Support) release—you'll notice bpf_spin_lock
appears (at the bottom).
This confirms that support for bpf_spin_lock
in BPF_PROG_TYPE_TRACING
was introduced starting from kernel version 5.15.
⭐️ BONUS TIP: To simplify all these manual steps, it could be worthwhile developing a tool that automatically performs something like a binary search across Linux kernel versions to pinpoint exactly when certain helpers were introduced.
As you’ve seen, checking whether a specific eBPF helper function is available for a particular program type isn't always straightforward.
Tools like bpftool and eBPF Docs are handy shortcuts, but they don’t always provide definitive or complete answers—especially when comparing multiple kernel versions.
If neither of these options fully meets your requirements, the most reliable method is still to dive directly into the Linux kernel source code and verify helper support yourself.
And if you happen to know a better, quicker, or more efficient method to determine helper availability across different program types and kernel versions, I'd be excited to hear your suggestions!
⏪ Did you miss the previous issues? I'm sure you wouldn't, but JUST in case:
I hope you find this resource helpful. Keep an eye out for more updates and developments in eBPF in next week's newsletter.
Until then, keep 🐝-ing!
Warm regards, Teodor and Patrick
Great blog to discover various helper functions based on kernel. I too have created a guide for the libbpf functions explaining the purpose, when to use, params, etc.
Link: https://hanshal101.github.io/hanshal101/blog/ebpf/a-comprehensive-guide-to-libbpf-functions/