llvm-objdump
You can take an eBPF object file and get a dump of its instructions through llvm-objdump
:
$ llvm-objdump -d ./.output/minimal.bpf.o
./.output/minimal.bpf.o: file format elf64-bpf
Disassembly of section tp/syscalls/sys_enter_write:
0000000000000000 <handle_tp>:
0: 85 00 00 00 0e 00 00 00 call 14
1: 77 00 00 00 20 00 00 00 r0 >>= 32
2: 18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
4: 61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
5: 5d 01 10 00 00 00 00 00 if r1 != r0 goto +16 <LBB0_2>
6: b7 01 00 00 64 2e 0a 00 r1 = 667236
7: 63 1a f8 ff 00 00 00 00 *(u32 *)(r10 - 8) = r1
8: 18 01 00 00 6f 6d 20 50 00 00 00 00 49 44 20 25 r1 = 2675213260325678447 ll
10: 7b 1a f0 ff 00 00 00 00 *(u64 *)(r10 - 16) = r1
11: 18 01 00 00 67 65 72 65 00 00 00 00 64 20 66 72 r1 = 8243311783519085927 ll
13: 7b 1a e8 ff 00 00 00 00 *(u64 *)(r10 - 24) = r1
14: 18 01 00 00 42 50 46 20 00 00 00 00 74 72 69 67 r1 = 7451612901544448066 ll
16: 7b 1a e0 ff 00 00 00 00 *(u64 *)(r10 - 32) = r1
17: bf a1 00 00 00 00 00 00 r1 = r10
18: 07 01 00 00 e0 ff ff ff r1 += -32
19: b7 02 00 00 1c 00 00 00 r2 = 28
20: bf 03 00 00 00 00 00 00 r3 = r0
21: 85 00 00 00 06 00 00 00 call 6
00000000000000b0 <LBB0_2>:
22: b7 00 00 00 00 00 00 00 r0 = 0
23: 95 00 00 00 00 00 00 00 exit
This object file is the minimal example from libbpf-bootstrap.
The instructions are displayed in little endian hex output. The first byte you see in each row represents the entire opcode of a bpf instruction.
Those 85
s are bpf helper function calls. You can tell because 0x05
is a 64-bit jump instruction class (BPF_JMP
), and 0x80
is the function call op (BPF_CALL
).
Use the bit-and operation on these (technically, you're supposed to bit-and another bit in the middle
but in this specific case it's just another 0x0
) and you'll get 0x85
.
There's also another new jump class: BPF_JMP32
. Can you combine this with the BPF_CALL
op
to do another form of helper function call? It doesn't seem so.