Decoding an eBPF instruction#

The Linux eBPF ISA documentation defines instruction fields using low-order bit labels and gives a concrete little-endian byte sequence for the instruction r1 += 0x11223344.

This example keeps the original bytes visible, then uses lsb0.le to read the fields using the same interpretation as the standard.

Standard reference: https://docs.kernel.org/bpf/standardization/instruction-set.html

from tibs import Tibs


# Linux's eBPF ISA documentation gives this little-endian instruction as:
#     r1 += 0x11223344
#
# The standard lays out the instruction fields using bit labels from the least
# significant end of the encoded word, so use an LSB0 view. The multi-byte
# offset and immediate fields are little-endian, so combine it with an LE view.
#
# https://docs.kernel.org/bpf/standardization/instruction-set.html
instruction_bytes = bytes.fromhex("07 01 00 00 44 33 22 11")
instruction = Tibs.from_bytes(instruction_bytes).lsb0.le

instruction_class = instruction.field(2, 0).u
source_mode = instruction.field(3, 3).u
operation_code = instruction.field(7, 4).u
dst_reg = instruction.field(11, 8).u
src_reg = instruction.field(15, 12).u
offset = instruction.field(31, 16).i
immediate = instruction.field(63, 32).u

assert instruction_class == 0x7   # BPF_ALU64.
assert source_mode == 0x0         # BPF_K.
assert operation_code == 0x0      # BPF_ADD.
assert dst_reg == 1
assert src_reg == 0
assert offset == 0
assert immediate == 0x11223344

assert f"r{dst_reg} += 0x{immediate:08x}" == "r1 += 0x11223344"