Home / Alt manpages / bpftool-btf(8)

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

Inspect Kernel BTF Safely with bpftool

You will finish with a small, repeatable workflow for listing loaded BTF objects, dumping their type information, and turning an ELF object's BTF into C declarations. The commands are read-only: they inspect metadata and do not load, unload or alter a BPF program.

Allow about fifteen minutes. You need a Linux shell, bpftool, and either a BTF-enabled running kernel or an ELF file containing a .BTF section. This guide follows the bpftool-btf(8) installed with linux-tools-common version 6.8.0-139.139. The command syntax and output can change with the bpftool and kernel versions.

Safety boundary

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

1. Check the local binary before interpreting output

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 systems, 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 there and resolve that packaging issue with your normal change process. Do not infer that BTF is absent from a wrapper error.

Checkpoint: the tool must be able to start before any BTF result is meaningful. On this machine the wrapper is present, but the matching kernel-specific executable is not, so the read-only commands below cannot be run locally until that dependency is supplied.

2. List the BTF objects currently loaded

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

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

The IDs, names and sizes are host-specific. Some systems show several module BTF objects; 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. The command does not accept a descriptive name in that position in this installed interface.

For scripts, request JSON rather than scraping the human-readable form:

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

The 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, while type_id= points at another entry. Read those references before assuming a line is self-contained.

To produce C-syntax output instead, select the format explicitly:

$ bpftool btf dump id BTF_ID format c

Use raw output when you need offsets, relationships and BTF IDs. Use C output when you want a quick view of structures and declarations. Neither format is a complete source file for your application.

4. Inspect a BTF-bearing file without changing the system

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. No sudo is normally needed for a file you can read.

5. Handle split module BTF deliberately

Kernel module BTF can be split and built on top of the kernel's vmlinux BTF. When dumping a module file, bpftool tries to find its base automatically. If the main object is supplied 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 actual BTF source or investigate whether the running kernel was built without it.

6. Inspect types attached to a map or program

When a map or program has associated BTF, use its 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. Select 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. Diagnose 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. They 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 that the module and base belong to the same kernel build.

None of the examples changes persistent configuration, BPF objects, mounts or services, so there is no undo operation. 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

  • You checked the installed bpftool wrapper and package version.
  • You listed BTF objects and treated their IDs as temporary host data.
  • You can dump an object by ID, file, map or program handle.
  • You know when to use raw output, C output, JSON or pretty JSON.
  • You can provide /sys/kernel/btf/vmlinux as a base for split module BTF.
  • You have kept inspection separate from loading, pinning and other changes.