How to Inspect Loaded eBPF Programs and Maps in Linux Using bpftool

Extended Berkeley Packet Filters (eBPF) have transformed the Linux kernel into a programmable, sandboxed execution environment. Modern observability agents, network load balancers (such as Cilium and Katran), and security enforcement frameworks (such as Tetragon and Falco) inject eBPF bytecode directly into kernel tracepoints, kprobes, and network socket layers. However, when troubleshooting system performance degradation, kernel memory overhead, or rogue network filters, administrators require visibility into exactly which programs and data maps are active in the kernel. The upstream bpftool utility provides the authoritative administrative command-line interface for auditing, dumping, and debugging live eBPF kernel state.

Architecture of eBPF Programs, Maps, and Links

The Linux kernel manages eBPF components through distinct object types:

  • eBPF Programs: Sandboxed bytecode verified by the kernel verifier and compiled into native machine instructions via the in-kernel Just-In-Time (JIT) compiler. Common program types include kprobe, tracepoint, xdp (eXpress Data Path), and cgroup/skb.
  • eBPF Maps: Generic key-value storage structures resident in kernel memory. Maps allow bidirectional communication and state sharing between user-space daemons and kernel-space eBPF programs. Common map types include hash, array, lpm_trie, and ringbuf.
  • eBPF Links (bpf_link): Kernel abstractions that pin an eBPF program to an attachment target (such as a network interface or cgroup). When the link object is closed or its file descriptor released, the program automatically detaches unless pinned to the BPF virtual filesystem (/sys/fs/bpf).

Installing bpftool on Modern Linux Distributions

The bpftool binary is distributed alongside the Linux kernel source tree. Install the toolchain via your distribution’s package manager:

# On Debian, Ubuntu, and derivatives
sudo apt update && sudo apt install -y linux-tools-common linux-tools-generic linux-tools-$(uname -r)

# On Fedora, CentOS Stream, and Rocky Linux
sudo dnf install -y bpftool

# On Arch Linux
sudo pacman -Sy bpf

Verify installation and kernel compatibility by running sudo bpftool version.

Auditing Loaded eBPF Programs

To view all active eBPF programs currently resident in the kernel across all processes, run:

# List all loaded eBPF programs
sudo bpftool prog show

# Query eBPF programs formatted as structured JSON for automation
sudo bpftool prog show --json --pretty

The output presents critical metadata for each active program:

342: sched_cls  name egress_filter  tag 7a42bc981df9831a  gpl
    loaded_at 2026-11-07T10:14:22+0000  uid 0
    xlated 424B  jited 268B  memlock 4096B  map_ids 112,114
    btf_id 84

Key indicators include:

  • Program ID (342): The unique runtime identifier assigned by the kernel.
  • Type (sched_cls): The attachment class (traffic control classifier).
  • xlated / jited: The size of the translated bytecode and the JIT-compiled native assembly in kernel memory.
  • map_ids (112, 114): The IDs of the kernel storage maps referenced by this program.

Dumping JIT-Compiled Assembly and Bytecode

To inspect the verified instructions of a loaded program without access to source code:

# Dump the human-readable translated bytecode instructions for program ID 342
sudo bpftool prog dump xlated id 342

# Dump the native CPU assembly instructions emitted by the JIT compiler
sudo bpftool prog dump jited id 342

If the program was compiled with BTF (BPF Type Format) debug information, bpftool interleaves the original C source lines directly within the disassembled instructions.

Inspecting eBPF Maps and Dumping Memory Contents

To audit kernel memory structures created by eBPF applications:

# List all active BPF maps in kernel memory
sudo bpftool map show

# Show detailed metadata for a specific map by ID
sudo bpftool map show id 112

# Dump all key-value entries stored in map 112
sudo bpftool map dump id 112

Dumping map entries enables administrators to view real-time connection tracking records, rate-limiting counters, and telemetry metrics stored directly inside kernel hash tables.

Tracking Pinned Objects in the BPF Virtual Filesystem

Modern service mesh daemons persist eBPF state across process restarts by pinning programs and maps to /sys/fs/bpf:

# Inspect pinned BPF objects across the filesystem
sudo bpftool prog show pinned /sys/fs/bpf/cilium_net_filter 2>/dev/null || ls -la /sys/fs/bpf/

# Pin an active program to the filesystem manually
sudo bpftool prog pin id 342 /sys/fs/bpf/my_custom_filter

Profiling eBPF Execution Performance and CPU Overhead

The Linux kernel can measure the exact CPU time consumed by individual eBPF programs. Enable performance profiling to identify expensive handlers:

# Enable runtime kernel statistics for BPF programs
sudo sysctl -w kernel.bpf_stats_enabled=1

# View program runtime and invocation frequency
sudo bpftool prog show

# Once diagnostics are complete, disable stats to eliminate instrumentation overhead
sudo sysctl -w kernel.bpf_stats_enabled=0

The run_time_ns and run_cnt fields illustrate how many nanoseconds the CPU spent inside the eBPF hook and how many packets or events triggered the program.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.