Operations 9 min read

eBPF Talk: Fixing a 7‑Year‑Old Bug in bpftool

The article details how a long‑standing bug that displayed incorrect call‑address information in bpftool’s JIT disassembly was reproduced, analyzed, and fixed by correcting the PC parameter to use the function’s kernel symbol address, with patches applied to both LLVM and libbfd back‑ends.

Linux Kernel Journey
Linux Kernel Journey
Linux Kernel Journey
eBPF Talk: Fixing a 7‑Year‑Old Bug in bpftool

Bug Reproduction

Running # bpftool prog dump jited name kprobe_skb_1 shows an incorrect call address (e.g., c70: call 0xffffffffd2702ab4). Examining the commit history confirms that every version of bpftool contains this error.

Investigation of the Disassembly Logic

Inspecting bpftool prog dump jited source reveals the core function disassemble_insn which ultimately calls LLVMDisasmInstruction(). The LLVM documentation states that the PC argument must be the instruction’s address.

size_t LLVMDisasmInstruction(LLVMDisasmContextRef DC, uint8_t *Bytes,
                               uint64_t BytesSize, uint64_t PC,
                               char *OutString, size_t OutStringSize);

Therefore the existing call passes pc (the instruction index) instead of the real address.

Patch Attempt – LLVM Path

The fix changes the pc argument to func_ksym + pc, where func_ksym is the start address of the BPF program image.

-count = LLVMDisasmInstruction(*ctx, image + pc, len - pc, pc,
+count = LLVMDisasmInstruction(*ctx, image + pc, len - pc, func_ksym + pc,
                                 buf, sizeof(buf));

The function signature is extended accordingly:

int disassemble_insn(disasm_ctx_t *ctx, unsigned char *image,
                    ssize_t len, int pc, __u64 func_ksym)

Building LLVM and bpftool with debugging symbols ( -g) and testing in gdb confirms that the corrected address is now used.

Patch Attempt – libbfd Path

When libbfd is the disassembly backend, relative‑address instructions (e.g., call, je) are also displayed incorrectly because the default print_address_func does not add the function’s base address.

The solution defines a custom disasm_print_addr that adds func_ksym before delegating to generic_print_address:

struct disasm_info { struct disassemble_info info; __u64 func_ksym; };

static void disasm_print_addr(bfd_vma addr, struct disassemble_info *info) {
    struct disasm_info *dinfo = container_of(info, struct disasm_info, info);
    addr += dinfo->func_ksym;
    generic_print_address(addr, info);
}

The info->print_address_func is set to this custom function, ensuring correct address calculation for relative instructions.

Conclusion

The patches correcting the PC calculation for both LLVM and libbfd backends have been merged into the Linux kernel’s BPF repository, eliminating a seven‑year‑old bug that caused misleading disassembly output.

References

Wrong callq address displayed: https://github.com/libbpf/bpftool/issues/109

Patch fixing disasm PC: https://lore.kernel.org/bpf/[email protected]/

LLVMDisasmInstruction documentation: https://llvm.org/doxygen/group__LLVMCDisassembler.html#gad1cbbd5aa7b51f04687926e8f9e4aebb

bpftool: Add LLVM as default library for disassembling JIT‑ed programs: https://github.com/torvalds/linux/commit/eb9d1acf634baf6401dfb4f67dc895290713a357

tools: bpf: add bpftool: https://github.com/torvalds/linux/commit/71bb428fe2c19512ac671d5ee16ef3e73e1b49a8

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

eBPFpatchLLVMkernel debuggingdisassemblybpftoollibbfd
Linux Kernel Journey
Written by

Linux Kernel Journey

Linux Kernel Journey

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.