Home / Alt manpages / bpftool-btf(8)

  • bpftool-btf(8)
  • Admin command
  • linux

Inspect Kernel BTF Data with bpftool

Dump a kernel's BTF type information with bpftool btf, or turn an ELF object's BTF into C declarations. You will list loaded BTF objects, dump their types and end with a small, repeatable workflow. Allow about fifteen minutes.

The commands are read-only: they inspect metadata and do not load, unload or alter a BPF program. This guide follows the bpftool-btf(8) installed with linux-tools-common version 6.8.0-139.139. Syntax and output can change with bpftool and kernel versions.

  • You need: a Linux shell, bpftool, and either a BTF-enabled running kernel or an ELF file containing a .BTF section.

Safety boundary

The examples only read BTF. A BTF dump is not proof that a program is safe, loaded, attached or enforcing a policy. It describes types, not runtime behaviour.

1. Check the local binary

Start with ordinary, unprivileged checks:

$ command -v bpftool
$ dpkg-query -W -f='${Package} ${Version}\n' linux-tools-common
linux-tools-common 6.8.0-139.139

On Ubuntu and Debian, bpftool can be a wrapper that looks for a binary matching the running kernel. If it reports that linux-tools-<kernel-version> is missing, stop and fix that packaging issue with your normal change process. A wrapper error does not mean BTF is absent.

Checkpoint

The tool must start before any BTF result means anything. On this machine the wrapper is present but the matching kernel-specific executable is not, so the read-only commands below cannot run locally until that dependency is supplied.

2. List loaded BTF objects

With a working binary, list every BTF object visible to the command:

$ bpftool btf show
[
    {
        id 1
        name vmlinux
        size 1234567B
    }
]

IDs, names and sizes are host-specific. Some systems show several module BTF objects, and an empty result is still a result. To inspect one object, add its numeric ID:

$ bpftool btf show id BTF_ID

Replace BTF_ID with a number from your own listing. In this installed interface the command does not accept a descriptive name in that position.

For scripts, ask for JSON instead of scraping the human-readable form:

$ bpftool btf show -j
[{"id":1,"name":"vmlinux","size":1234567}]

Actual fields and values depend on the host. Add -p for indented, human-readable JSON; it implies -j. If access to the kernel's BPF interfaces is denied, retrying with sudo may be appropriate, but privilege does not create a missing BTF object.

3. Dump a kernel BTF object by ID

Use the ID from the previous step to print all of that object's BTF types in the default raw format:

$ bpftool btf dump id BTF_ID
[1] PTR '(anon)' type_id=2
[2] STRUCT 'example_type' size=16 vlen=2
        'field' type_id=3 bits_offset=0

Real output can include INT, STRUCT, UNION, ENUM, FUNC, VAR and other kinds. The number in square brackets is the BTF type ID, and type_id= points at another entry. Follow those references before assuming a line stands alone.

For C-syntax output, select the format explicitly:

$ bpftool btf dump id BTF_ID format c
  • Raw output: use it when you need offsets, relationships and BTF IDs.
  • C output: use it for a quick view of structures and declarations.
  • Neither is a complete source file for your application.

4. Dump BTF from a file

An ELF object produced by a compiler or by pahole may contain a .BTF section. Dump it directly:

$ bpftool btf dump file ./build/program.bpf.o
[1] PTR '(anon)' type_id=2
[2] STRUCT 'event' size=32 vlen=2
        'pid' type_id=3 bits_offset=0
        'comm' type_id=4 bits_offset=32

If the file is not an ELF object with valid BTF data, expect an error rather than a useful dump. Check the file before blaming the kernel:

$ file ./build/program.bpf.o
$ readelf -S ./build/program.bpf.o | grep -E '\.BTF|\.BTF\.ext'

The readelf and file commands are also read-only. A file you can read normally needs no sudo.

5. Supply a base for split module BTF

Kernel module BTF can be split and built on top of the kernel's vmlinux BTF. When you dump a module file, bpftool tries to find its base automatically. If the main object comes through an ID or another handle, or autodetection fails, pass the base explicitly:

$ bpftool btf dump id BTF_ID -B /sys/kernel/btf/vmlinux

-B or --base-btf names the base BTF file. The usual base for a module is /sys/kernel/btf/vmlinux, but verify that the path exists on the target machine:

$ test -r /sys/kernel/btf/vmlinux && echo 'base BTF is readable'
base BTF is readable

If the test fails, do not substitute an arbitrary file. Find the kernel's real BTF source, or check whether the running kernel was built without it.

6. Dump BTF for a map or program

When a map or program has associated BTF, address it by ID, tag or pinned path:

$ bpftool btf dump map id MAP_ID
$ bpftool btf dump map pinned /sys/fs/bpf/MAP_NAME
$ bpftool btf dump prog id PROG_ID
$ bpftool btf dump prog tag PROG_TAG
$ bpftool btf dump prog pinned /sys/fs/bpf/PROG_NAME

For a map, the default is both key and value types. Pick one side, both explicitly, or every type in the associated BTF object with key, value, kv or all:

$ bpftool btf dump map id MAP_ID key
$ bpftool btf dump map id MAP_ID value
$ bpftool btf dump map id MAP_ID kv
$ bpftool btf dump map id MAP_ID all

These commands inspect existing kernel objects. They may need elevated privileges or access to /sys/fs/bpf. Use the least privilege that works, and treat pinned paths and IDs as inputs to verify, not as permission to modify or remove anything.

7. Avoid the common traps

  • Missing wrapper target: a message naming linux-tools-$(uname -r) is a packaging problem. It is not evidence that the kernel lacks BTF.
  • Wrong ID: BTF IDs are runtime identifiers and can differ after a reboot or object reload. List them again instead of reusing an old number.
  • Unreadable file: confirm the path, ownership and permissions. Do not make a system BTF file world-readable just to avoid a controlled privilege check.
  • Unexpectedly large output: raw dumps include every type. Use a map's key or value selector where that answers the question, and redirect output to a deliberate report path.
  • Module errors: retry with the correct vmlinux base only after confirming the module and base belong to the same kernel build.

Recovery

None of the examples changes persistent configuration, BPF objects, mounts or services, so there is nothing to undo. If a later investigation asks you to load, pin, unpin or remove an object, stop and review that separate, state-changing procedure first.

Done means

  • Binary checked. You checked the installed bpftool wrapper and package version.
  • IDs treated as temporary. You listed BTF objects and treated their IDs as host data that will change.
  • Dump routes known. You can dump an object by ID, file, map or program handle.
  • Formats chosen. You know when to use raw output, C output, JSON or pretty JSON.
  • Base supplied. You can pass /sys/kernel/btf/vmlinux as the base for split module BTF.
  • Inspection kept separate. Loading, pinning and other changes stayed out of it.