add i32 support special case and find ctx repetition in multiple functions error.

This commit is contained in:
2025-11-05 17:38:38 +05:30
parent 3489f45b63
commit 2685d0a0ee
6 changed files with 63 additions and 19 deletions

View File

@ -81,7 +81,7 @@ def _allocate_for_call(builder, var_name, rval, local_sym_tab, structs_sym_tab):
call_type = rval.func.id
# C type constructors
if call_type in ("c_int32", "c_int64", "c_uint32", "c_uint64"):
if call_type in ("c_int32", "c_int64", "c_uint32", "c_uint64", "c_void_p"):
ir_type = ctypes_to_ir(call_type)
var = builder.alloca(ir_type, name=var_name)
var.align = ir_type.width // 8
@ -259,7 +259,16 @@ def _allocate_for_attribute(builder, var_name, rval, local_sym_tab, structs_sym_
field_size_bits = field_size_bytes * 8
if field_size_bits in [8, 16, 32, 64]:
actual_ir_type = ir.IntType(field_size_bits)
# Special case: struct_xdp_md i32 fields should allocate as i64
# because load_ctx_field will zero-extend them to i64
if vmlinux_struct_name == "struct_xdp_md" and field_size_bits == 32:
actual_ir_type = ir.IntType(64)
logger.info(
f"Allocating {var_name} as i64 for i32 field from struct_xdp_md.{field_name} "
"(will be zero-extended during load)"
)
else:
actual_ir_type = ir.IntType(field_size_bits)
else:
logger.warning(
f"Unusual field size {field_size_bits} bits for {field_name}"

View File

@ -152,15 +152,26 @@ def handle_variable_assignment(
if val_type != var_type:
if isinstance(val_type, Field):
logger.info("Handling assignment to struct field")
# Special handling for struct_xdp_md i32 fields that are zero-extended to i64
# The load_ctx_field already extended them, so val is i64 but val_type.type shows c_uint
if (hasattr(val_type, 'type') and
val_type.type.__name__ == "c_uint" and
isinstance(var_type, ir.IntType) and
var_type.width == 64):
# This is the struct_xdp_md case - value is already i64
builder.store(val, var_ptr)
logger.info(f"Assigned zero-extended struct_xdp_md i32 field to {var_name} (i64)")
return True
# TODO: handling only ctype struct fields for now. Handle other stuff too later.
if var_type == ctypes_to_ir(val_type.type.__name__):
elif var_type == ctypes_to_ir(val_type.type.__name__):
builder.store(val, var_ptr)
logger.info(f"Assigned ctype struct field to {var_name}")
return True
logger.error(
f"Failed to assign ctype struct field to {var_name}: {val_type} != {var_type}"
)
return False
else:
logger.error(
f"Failed to assign ctype struct field to {var_name}: {val_type} != {var_type}"
)
return False
elif isinstance(val_type, ir.IntType) and isinstance(var_type, ir.IntType):
# Allow implicit int widening
if val_type.width < var_type.width:

View File

@ -94,12 +94,13 @@ class VmlinuxHandler:
f"Attempting to access field {field_name} of possible vmlinux struct {struct_var_name}"
)
python_type: type = var_info.metadata
struct_name = python_type.__name__
globvar_ir, field_data = self.get_field_type(
python_type.__name__, field_name
struct_name, field_name
)
builder.function.args[0].type = ir.PointerType(ir.IntType(8))
field_ptr = self.load_ctx_field(
builder, builder.function.args[0], globvar_ir, field_data
builder, builder.function.args[0], globvar_ir, field_data, struct_name
)
# Return pointer to field and field type
return field_ptr, field_data
@ -107,7 +108,7 @@ class VmlinuxHandler:
raise RuntimeError("Variable accessed not found in symbol table")
@staticmethod
def load_ctx_field(builder, ctx_arg, offset_global, field_data):
def load_ctx_field(builder, ctx_arg, offset_global, field_data, struct_name=None):
"""
Generate LLVM IR to load a field from BPF context using offset.
@ -116,8 +117,9 @@ class VmlinuxHandler:
ctx_arg: The context pointer argument (ptr/i8*)
offset_global: Global variable containing the field offset (i64)
field_data: contains data about the field
struct_name: Name of the struct being accessed (optional)
Returns:
The loaded value (i64 register)
The loaded value (i64 register or appropriately sized)
"""
# Load the offset value
@ -164,6 +166,7 @@ class VmlinuxHandler:
# Determine the appropriate IR type based on field information
int_width = 64 # Default to 64-bit
needs_zext = False # Track if we need zero-extension for xdp_md
if field_data is not None:
# Try to determine the size from field metadata
@ -175,6 +178,12 @@ class VmlinuxHandler:
if field_size_bits in [8, 16, 32, 64]:
int_width = field_size_bits
logger.info(f"Determined field size: {int_width} bits")
# Special handling for struct_xdp_md i32 fields
# Load as i32 but extend to i64 before storing
if struct_name == "struct_xdp_md" and int_width == 32:
needs_zext = True
logger.info(f"struct_xdp_md i32 field detected, will zero-extend to i64")
else:
logger.warning(
f"Unusual field size {field_size_bits} bits, using default 64"
@ -203,6 +212,11 @@ class VmlinuxHandler:
# Load and return the value
value = builder.load(typed_ptr)
# Zero-extend i32 to i64 for struct_xdp_md fields
if needs_zext:
value = builder.zext(value, ir.IntType(64))
logger.info("Zero-extended i32 value to i64 for struct_xdp_md field")
return value
def has_field(self, struct_name, field_name):