mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2026-02-12 16:10:59 +00:00
Compare commits
4 Commits
209df33c8f
...
56df05a93c
| Author | SHA1 | Date | |
|---|---|---|---|
| 56df05a93c | |||
| a55efc6469 | |||
| 64cd2d2fc2 | |||
| cbddc0aa96 |
@ -26,7 +26,7 @@ classifiers = [
|
|||||||
]
|
]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
requires-python = ">=3.8"
|
requires-python = ">=3.10"
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"llvmlite",
|
"llvmlite",
|
||||||
|
|||||||
@ -218,13 +218,11 @@ def compile(loglevel=logging.WARNING) -> bool:
|
|||||||
def BPF(loglevel=logging.WARNING) -> BpfObject:
|
def BPF(loglevel=logging.WARNING) -> BpfObject:
|
||||||
caller_frame = inspect.stack()[1]
|
caller_frame = inspect.stack()[1]
|
||||||
src = inspect.getsource(caller_frame.frame)
|
src = inspect.getsource(caller_frame.frame)
|
||||||
with tempfile.NamedTemporaryFile(
|
with (
|
||||||
mode="w+", delete=True, suffix=".py"
|
tempfile.NamedTemporaryFile(mode="w+", delete=True, suffix=".py") as f,
|
||||||
) as f, tempfile.NamedTemporaryFile(
|
tempfile.NamedTemporaryFile(mode="w+", delete=True, suffix=".ll") as inter,
|
||||||
mode="w+", delete=True, suffix=".ll"
|
tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".o") as obj_file,
|
||||||
) as inter, tempfile.NamedTemporaryFile(
|
):
|
||||||
mode="w+", delete=False, suffix=".o"
|
|
||||||
) as obj_file:
|
|
||||||
f.write(src)
|
f.write(src)
|
||||||
f.flush()
|
f.flush()
|
||||||
source = f.name
|
source = f.name
|
||||||
|
|||||||
@ -12,11 +12,10 @@ from .helper_utils import (
|
|||||||
get_int_value_from_arg,
|
get_int_value_from_arg,
|
||||||
)
|
)
|
||||||
from .printk_formatter import simple_string_print, handle_fstring_print
|
from .printk_formatter import simple_string_print, handle_fstring_print
|
||||||
|
from pythonbpf.maps import BPFMapType
|
||||||
from logging import Logger
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger: Logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BPFHelperID(Enum):
|
class BPFHelperID(Enum):
|
||||||
@ -362,11 +361,6 @@ def bpf_get_current_pid_tgid_emitter(
|
|||||||
return pid, ir.IntType(64)
|
return pid, ir.IntType(64)
|
||||||
|
|
||||||
|
|
||||||
@HelperHandlerRegistry.register(
|
|
||||||
"output",
|
|
||||||
param_types=[ir.PointerType(ir.IntType(8))],
|
|
||||||
return_type=ir.IntType(64),
|
|
||||||
)
|
|
||||||
def bpf_perf_event_output_handler(
|
def bpf_perf_event_output_handler(
|
||||||
call,
|
call,
|
||||||
map_ptr,
|
map_ptr,
|
||||||
@ -377,6 +371,10 @@ def bpf_perf_event_output_handler(
|
|||||||
struct_sym_tab=None,
|
struct_sym_tab=None,
|
||||||
map_sym_tab=None,
|
map_sym_tab=None,
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
Emit LLVM IR for bpf_perf_event_output helper function call.
|
||||||
|
"""
|
||||||
|
|
||||||
if len(call.args) != 1:
|
if len(call.args) != 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Perf event output expects exactly one argument, got {len(call.args)}"
|
f"Perf event output expects exactly one argument, got {len(call.args)}"
|
||||||
@ -414,6 +412,98 @@ def bpf_perf_event_output_handler(
|
|||||||
return result, None
|
return result, None
|
||||||
|
|
||||||
|
|
||||||
|
def bpf_ringbuf_output_emitter(
|
||||||
|
call,
|
||||||
|
map_ptr,
|
||||||
|
module,
|
||||||
|
builder,
|
||||||
|
func,
|
||||||
|
local_sym_tab=None,
|
||||||
|
struct_sym_tab=None,
|
||||||
|
map_sym_tab=None,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Emit LLVM IR for bpf_ringbuf_output helper function call.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(call.args) != 1:
|
||||||
|
raise ValueError(
|
||||||
|
f"Ringbuf output expects exactly one argument, got {len(call.args)}"
|
||||||
|
)
|
||||||
|
data_arg = call.args[0]
|
||||||
|
data_ptr, size_val = get_data_ptr_and_size(data_arg, local_sym_tab, struct_sym_tab)
|
||||||
|
flags_val = ir.Constant(ir.IntType(64), 0)
|
||||||
|
|
||||||
|
map_void_ptr = builder.bitcast(map_ptr, ir.PointerType())
|
||||||
|
data_void_ptr = builder.bitcast(data_ptr, ir.PointerType())
|
||||||
|
fn_type = ir.FunctionType(
|
||||||
|
ir.IntType(64),
|
||||||
|
[
|
||||||
|
ir.PointerType(),
|
||||||
|
ir.PointerType(),
|
||||||
|
ir.IntType(64),
|
||||||
|
ir.IntType(64),
|
||||||
|
],
|
||||||
|
var_arg=False,
|
||||||
|
)
|
||||||
|
fn_ptr_type = ir.PointerType(fn_type)
|
||||||
|
|
||||||
|
# helper id
|
||||||
|
fn_addr = ir.Constant(ir.IntType(64), BPFHelperID.BPF_RINGBUF_OUTPUT.value)
|
||||||
|
fn_ptr = builder.inttoptr(fn_addr, fn_ptr_type)
|
||||||
|
|
||||||
|
result = builder.call(
|
||||||
|
fn_ptr, [map_void_ptr, data_void_ptr, size_val, flags_val], tail=False
|
||||||
|
)
|
||||||
|
return result, None
|
||||||
|
|
||||||
|
|
||||||
|
@HelperHandlerRegistry.register(
|
||||||
|
"output",
|
||||||
|
param_types=[ir.PointerType(ir.IntType(8))],
|
||||||
|
return_type=ir.IntType(64),
|
||||||
|
)
|
||||||
|
def handle_output_helper(
|
||||||
|
call,
|
||||||
|
map_ptr,
|
||||||
|
module,
|
||||||
|
builder,
|
||||||
|
func,
|
||||||
|
local_sym_tab=None,
|
||||||
|
struct_sym_tab=None,
|
||||||
|
map_sym_tab=None,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Route output helper to the appropriate emitter based on map type.
|
||||||
|
"""
|
||||||
|
match map_sym_tab[map_ptr.name].type:
|
||||||
|
case BPFMapType.PERF_EVENT_ARRAY:
|
||||||
|
return bpf_perf_event_output_handler(
|
||||||
|
call,
|
||||||
|
map_ptr,
|
||||||
|
module,
|
||||||
|
builder,
|
||||||
|
func,
|
||||||
|
local_sym_tab,
|
||||||
|
struct_sym_tab,
|
||||||
|
map_sym_tab,
|
||||||
|
)
|
||||||
|
case BPFMapType.RINGBUF:
|
||||||
|
return bpf_ringbuf_output_emitter(
|
||||||
|
call,
|
||||||
|
map_ptr,
|
||||||
|
module,
|
||||||
|
builder,
|
||||||
|
func,
|
||||||
|
local_sym_tab,
|
||||||
|
struct_sym_tab,
|
||||||
|
map_sym_tab,
|
||||||
|
)
|
||||||
|
case _:
|
||||||
|
logger.error("Unsupported map type for output helper.")
|
||||||
|
raise NotImplementedError("Output helper for this map type is not implemented.")
|
||||||
|
|
||||||
|
|
||||||
def emit_probe_read_kernel_str_call(builder, dst_ptr, dst_size, src_ptr):
|
def emit_probe_read_kernel_str_call(builder, dst_ptr, dst_size, src_ptr):
|
||||||
"""Emit LLVM IR call to bpf_probe_read_kernel_str"""
|
"""Emit LLVM IR call to bpf_probe_read_kernel_str"""
|
||||||
|
|
||||||
@ -904,6 +994,6 @@ def handle_helper_call(
|
|||||||
if not map_sym_tab or map_name not in map_sym_tab:
|
if not map_sym_tab or map_name not in map_sym_tab:
|
||||||
raise ValueError(f"Map '{map_name}' not found in symbol table")
|
raise ValueError(f"Map '{map_name}' not found in symbol table")
|
||||||
|
|
||||||
return invoke_helper(method_name, map_sym_tab[map_name])
|
return invoke_helper(method_name, map_sym_tab[map_name].sym)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
from .maps import HashMap, PerfEventArray, RingBuffer
|
from .maps import HashMap, PerfEventArray, RingBuffer
|
||||||
from .maps_pass import maps_proc
|
from .maps_pass import maps_proc
|
||||||
|
from .map_types import BPFMapType
|
||||||
|
|
||||||
__all__ = ["HashMap", "PerfEventArray", "maps_proc", "RingBuffer"]
|
__all__ = ["HashMap", "PerfEventArray", "maps_proc", "RingBuffer", "BPFMapType"]
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import logging
|
|||||||
from logging import Logger
|
from logging import Logger
|
||||||
from llvmlite import ir
|
from llvmlite import ir
|
||||||
|
|
||||||
from .maps_utils import MapProcessorRegistry
|
from .maps_utils import MapProcessorRegistry, MapSymbol
|
||||||
from .map_types import BPFMapType
|
from .map_types import BPFMapType
|
||||||
from .map_debug_info import create_map_debug_info, create_ringbuf_debug_info
|
from .map_debug_info import create_map_debug_info, create_ringbuf_debug_info
|
||||||
from pythonbpf.expr.vmlinux_registry import VmlinuxHandlerRegistry
|
from pythonbpf.expr.vmlinux_registry import VmlinuxHandlerRegistry
|
||||||
@ -46,7 +46,7 @@ def create_bpf_map(module, map_name, map_params):
|
|||||||
map_global.align = 8
|
map_global.align = 8
|
||||||
|
|
||||||
logger.info(f"Created BPF map: {map_name} with params {map_params}")
|
logger.info(f"Created BPF map: {map_name} with params {map_params}")
|
||||||
return map_global
|
return MapSymbol(type=map_params["type"], sym=map_global)
|
||||||
|
|
||||||
|
|
||||||
def _parse_map_params(rval, expected_args=None):
|
def _parse_map_params(rval, expected_args=None):
|
||||||
@ -100,7 +100,7 @@ def process_ringbuf_map(map_name, rval, module):
|
|||||||
logger.info(f"Ringbuf map parameters: {map_params}")
|
logger.info(f"Ringbuf map parameters: {map_params}")
|
||||||
|
|
||||||
map_global = create_bpf_map(module, map_name, map_params)
|
map_global = create_bpf_map(module, map_name, map_params)
|
||||||
create_ringbuf_debug_info(module, map_global, map_name, map_params)
|
create_ringbuf_debug_info(module, map_global.sym, map_name, map_params)
|
||||||
return map_global
|
return map_global
|
||||||
|
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ def process_hash_map(map_name, rval, module):
|
|||||||
logger.info(f"Map parameters: {map_params}")
|
logger.info(f"Map parameters: {map_params}")
|
||||||
map_global = create_bpf_map(module, map_name, map_params)
|
map_global = create_bpf_map(module, map_name, map_params)
|
||||||
# Generate debug info for BTF
|
# Generate debug info for BTF
|
||||||
create_map_debug_info(module, map_global, map_name, map_params)
|
create_map_debug_info(module, map_global.sym, map_name, map_params)
|
||||||
return map_global
|
return map_global
|
||||||
|
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ def process_perf_event_map(map_name, rval, module):
|
|||||||
logger.info(f"Map parameters: {map_params}")
|
logger.info(f"Map parameters: {map_params}")
|
||||||
map_global = create_bpf_map(module, map_name, map_params)
|
map_global = create_bpf_map(module, map_name, map_params)
|
||||||
# Generate debug info for BTF
|
# Generate debug info for BTF
|
||||||
create_map_debug_info(module, map_global, map_name, map_params)
|
create_map_debug_info(module, map_global.sym, map_name, map_params)
|
||||||
return map_global
|
return map_global
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,16 @@
|
|||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from llvmlite import ir
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
from .map_types import BPFMapType
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MapSymbol:
|
||||||
|
"""Class representing a symbol on the map"""
|
||||||
|
|
||||||
|
type: BPFMapType
|
||||||
|
sym: ir.GlobalVariable
|
||||||
|
|
||||||
|
|
||||||
class MapProcessorRegistry:
|
class MapProcessorRegistry:
|
||||||
|
|||||||
Reference in New Issue
Block a user