add i32 support and make it extensible

This commit is contained in:
2025-11-01 14:43:19 +05:30
parent a9d82d40d3
commit 204ec26154
8 changed files with 153 additions and 13 deletions

View File

@ -1,6 +1,6 @@
import logging
from typing import Any
import ctypes
from llvmlite import ir
from pythonbpf.local_symbol import LocalSymbol
@ -98,18 +98,16 @@ class VmlinuxHandler:
python_type.__name__, field_name
)
builder.function.args[0].type = ir.PointerType(ir.IntType(8))
print(builder.function.args[0])
field_ptr = self.load_ctx_field(
builder, builder.function.args[0], globvar_ir
builder, builder.function.args[0], globvar_ir, field_data
)
print(field_ptr)
# Return pointer to field and field type
return field_ptr, field_data
else:
raise RuntimeError("Variable accessed not found in symbol table")
@staticmethod
def load_ctx_field(builder, ctx_arg, offset_global):
def load_ctx_field(builder, ctx_arg, offset_global, field_data):
"""
Generate LLVM IR to load a field from BPF context using offset.
@ -117,7 +115,7 @@ class VmlinuxHandler:
builder: llvmlite IRBuilder instance
ctx_arg: The context pointer argument (ptr/i8*)
offset_global: Global variable containing the field offset (i64)
field_data: contains data about the field
Returns:
The loaded value (i64 register)
"""
@ -164,9 +162,43 @@ class VmlinuxHandler:
passthrough_fn, [ir.Constant(ir.IntType(32), 0), field_ptr], tail=True
)
# Bitcast to i64* (assuming field is 64-bit, adjust if needed)
i64_ptr_type = ir.PointerType(ir.IntType(64))
typed_ptr = builder.bitcast(verified_ptr, i64_ptr_type)
# Determine the appropriate IR type based on field information
int_width = 64 # Default to 64-bit
if field_data is not None:
# Try to determine the size from field metadata
if field_data.type.__module__ == ctypes.__name__:
try:
field_size_bytes = ctypes.sizeof(field_data.type)
field_size_bits = field_size_bytes * 8
if field_size_bits in [8, 16, 32, 64]:
int_width = field_size_bits
logger.info(f"Determined field size: {int_width} bits")
else:
logger.warning(
f"Unusual field size {field_size_bits} bits, using default 64"
)
except Exception as e:
logger.warning(
f"Could not determine field size: {e}, using default 64"
)
elif field_data.type.__module__ == "vmlinux":
# For pointers to structs or complex vmlinux types
if field_data.ctype_complex_type is not None and issubclass(
field_data.ctype_complex_type, ctypes._Pointer
):
int_width = 64 # Pointers are always 64-bit
logger.info("Field is a pointer type, using 64 bits")
# TODO: Add handling for other complex types (arrays, embedded structs, etc.)
else:
logger.warning("Complex vmlinux field type, using default 64 bits")
# Bitcast to appropriate pointer type based on determined width
ptr_type = ir.PointerType(ir.IntType(int_width))
typed_ptr = builder.bitcast(verified_ptr, ptr_type)
# Load and return the value
value = builder.load(typed_ptr)