An eBPF instruction set simulator for hardware verification that parses LLVM-compiled eBPF relocatable object files and generates execution traces in a format that can be used for Hardware verification.
- Parses relocatable ELF object files (
.o) compiled from eBPF programs - Simulates eBPF instruction execution
- Generates execution traces with register and memory updates
- Supports all major eBPF instruction classes:
- ALU/ALU64 operations (register and immediate)
- Memory operations (LD, ST, LDX, STX)
- Jump instructions (JMP, JMP32)
- Special instructions (EXIT, MOV, etc.)
- Configurable stack pointer (r10) initialization
- Human-readable disassembly matching objdump format
- Python 3.6 or higher
- LLVM/Clang (for compiling eBPF programs)
No installation required. Simply ensure you have Python 3 installed:
python3 --versionpython3 main.py <input_file.o> [-o output_file] [--r10 value]input_file: Path to the LLVM-compiled eBPF relocatable object file (.o)-o, --output: Optional output file path (default: stdout)--r10: Optional initial value for r10 (stack pointer) in hex (e.g.,0x1000) or decimal (e.g.,4096)
# Run simulator and output to stdout
python3 main.py bpf.o
# Save output to a file
python3 main.py bpf.o -o trace.txt
# Set initial stack pointer to 0x1000
python3 main.py bpf.o --r10 0x1000
# Set initial stack pointer to 4096 (decimal)
python3 main.py bpf.o --r10 4096 -o trace.txtThis simulator works with relocatable ELF object files compiled from eBPF programs. You can generate compatible object files using LLVM/Clang.
Based on the LLVM eBPF assembly guide:
-
Compile C source to eBPF assembly:
clang -target bpf -S -o bpf.s bpf.c
-
Assemble to ELF object file:
llvm-mc -triple bpf -filetype=obj -o bpf.o bpf.s
For simple programs, you can compile directly:
clang -target bpf -Wall -O2 -c bpf.c -o bpf.oSome programs may need the -mcpu option:
clang -O2 -emit-llvm -c bpf.c -o - | \
llc -march=bpf -mcpu=probe -filetype=obj -o bpf.oCreate a simple eBPF program in C:
// bpf.c
int func()
{
return 0;
}Compile it:
clang -target bpf -S -o bpf.s bpf.c
llvm-mc -triple bpf -filetype=obj -o bpf.o bpf.sThen run the simulator:
python3 main.py bpf.oYou can inspect the compiled eBPF object file using llvm-objdump:
llvm-objdump -d bpf.oFor disassembly with source code (if compiled with -g):
llvm-objdump -S bpf.oThe simulator generates execution traces in the following format:
<address>;<instruction_bytes>;<disassembly>;[<register_updates>]
Where:
address: Instruction address in hex (8 digits)instruction_bytes: Raw instruction bytes in hex (uppercase)disassembly: Human-readable assembly instructionregister_updates: Optional semicolon-separated list of register/memory updates
0x00000000;0xB701000000000000;r1 = 0;r1=0x0000000000000000
0x00000008;0x631AFCFF00000000;*(u32 *)(r10 - 0x4) = r1;mem[0x00000000FFFFFFFC]=0x0000000000000000
0x00000010;0xBF10000000000000;r0 = r1;r0=0x0000000000000000
0x00000018;0x9500000000000000;exit;exit
- Register updates:
r<num>=0x<value>(16 hex digits) - Memory updates:
mem[0x<address>]=0x<value>(16 hex digits)
The simulator models all 11 eBPF registers (R0-R10):
- R0: Return value
- R1-R5: Function arguments (caller-saved)
- R6-R9: Callee-saved registers
- R10: Read-only frame pointer (stack pointer)
- Only supports relocatable ELF files (ET_REL), not executables
- Helper function calls (CALL instruction) are not implemented
- Maximum instruction execution limit: 10,000 instructions (safety limit)
- Stack size: 512 bytes
Apache 2.0 License