linux: bpf_prog: Add methods to get the program address and its memory regions

This commit is contained in:
Gustavo Moreira
2025-02-01 17:55:05 +11:00
parent 0e0daffc45
commit e2431eebdf
@@ -2103,6 +2103,10 @@ class xdp_sock(objects.StructType):
class bpf_prog(objects.StructType):
_BPF_PROG_CHUNK_SHIFT = 6
_BPF_PROG_CHUNK_SIZE = 1 << _BPF_PROG_CHUNK_SHIFT
_BPF_PROG_CHUNK_MASK = ~(_BPF_PROG_CHUNK_SIZE - 1)
def get_type(self) -> Union[str, None]:
"""Returns a string with the eBPF program type"""
@@ -2147,6 +2151,58 @@ class bpf_prog(objects.StructType):
return self.aux.get_name()
def bpf_jit_binary_hdr_address(self) -> int:
"""Return the jitted BPF program start address
Based on bpf_jit_binary_hdr()
Returns:
The BPF program address
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name]
# In 5.18 (33c9805860e584b194199cab1a1e81f4e6395408) <= kernels < 6.0 (1d5f82d9dd477d5c66e0214a68c3e4f308eadd6d)
# 'bpf_prog_aux' has a 'use_bpf_prog_pack' member
bpf_prog_aux_has_use_bpf_prog_pack = vmlinux.get_type(
"bpf_prog_aux"
).has_member("use_bpf_prog_pack")
if bpf_prog_aux_has_use_bpf_prog_pack and self.aux.use_bpf_prog_pack:
long_mask = (1 << vmlinux_layer.bits_per_register) - 1
addr_mask = self._BPF_PROG_CHUNK_MASK & long_mask
else:
addr_mask = vmlinux_layer.page_mask
real_start = self.bpf_func
return real_start & addr_mask
def get_address_region(self) -> Tuple[int, int]:
"""Returns the start and end memory addresses of the BPF program.
Based on bpf_get_prog_addr_region()
Returns:
A tuple with the addresses representing the memory range (start, end) of the BPF program.
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name]
# Based on bpf_get_prog_addr_region()
bpf_start_address = self.bpf_jit_binary_hdr_address()
if vmlinux.has_type("bpf_binary_header"):
# kernels >= 3.11 314beb9bcabfd6b4542ccbced2402af2c6f6142a
bpf_binary_header = vmlinux.object(
object_type="bpf_binary_header", offset=bpf_start_address, absolute=True
)
pages = bpf_binary_header.pages
else:
# kernels < 3.11 The first member is always the size
pages = vmlinux.object(
object_type="unsigned int", offset=bpf_start_address, absolute=True
)
bpf_end_address = bpf_start_address + pages * vmlinux_layer.page_size
return bpf_start_address, bpf_end_address
class bpf_prog_aux(objects.StructType):
def get_name(self) -> Union[str, None]: