diff --git a/pythonbpf/vmlinux_parser/class_handler.py b/pythonbpf/vmlinux_parser/class_handler.py index 6ef70ba..48668a2 100644 --- a/pythonbpf/vmlinux_parser/class_handler.py +++ b/pythonbpf/vmlinux_parser/class_handler.py @@ -25,7 +25,7 @@ def process_vmlinux_class(node, llvm_module, handler: DependencyHandler): def process_vmlinux_post_ast( - elem_type_class, llvm_handler, handler: DependencyHandler, processing_stack=None + elem_type_class, llvm_handler, handler: DependencyHandler, processing_stack=None ): # Initialize processing stack on first call if processing_stack is None: diff --git a/pythonbpf/vmlinux_parser/dependency_node.py b/pythonbpf/vmlinux_parser/dependency_node.py index 3046f32..e266761 100644 --- a/pythonbpf/vmlinux_parser/dependency_node.py +++ b/pythonbpf/vmlinux_parser/dependency_node.py @@ -35,7 +35,7 @@ class Field: self.ready = True def set_containing_type( - self, containing_type: Optional[Any], mark_ready: bool = False + self, containing_type: Optional[Any], mark_ready: bool = False ) -> None: """Set the containing_type of this field and optionally mark it as ready.""" self.containing_type = containing_type @@ -49,7 +49,7 @@ class Field: self.ready = True def set_ctype_complex_type( - self, ctype_complex_type: Any, mark_ready: bool = False + self, ctype_complex_type: Any, mark_ready: bool = False ) -> None: """Set the ctype_complex_type of this field and optionally mark it as ready.""" self.ctype_complex_type = ctype_complex_type @@ -119,16 +119,16 @@ class DependencyNode: ctype_struct: Optional[Any] = field(default=None, repr=False) def add_field( - self, - name: str, - field_type: type, - initial_value: Any = None, - containing_type: Optional[Any] = None, - type_size: Optional[int] = None, - ctype_complex_type: Optional[int] = None, - bitfield_size: Optional[int] = None, - ready: bool = False, - offset: int = 0, + self, + name: str, + field_type: type, + initial_value: Any = None, + containing_type: Optional[Any] = None, + type_size: Optional[int] = None, + ctype_complex_type: Optional[int] = None, + bitfield_size: Optional[int] = None, + ready: bool = False, + offset: int = 0, ) -> None: """Add a field to the node with an optional initial value and readiness state.""" if self.depends_on is None: @@ -180,7 +180,7 @@ class DependencyNode: self._ready_cache = None def set_field_containing_type( - self, name: str, containing_type: Any, mark_ready: bool = False + self, name: str, containing_type: Any, mark_ready: bool = False ) -> None: """Set a field's containing_type and optionally mark it as ready.""" if name not in self.fields: @@ -191,7 +191,7 @@ class DependencyNode: self._ready_cache = None def set_field_type_size( - self, name: str, type_size: Any, mark_ready: bool = False + self, name: str, type_size: Any, mark_ready: bool = False ) -> None: """Set a field's type_size and optionally mark it as ready.""" if name not in self.fields: @@ -202,7 +202,7 @@ class DependencyNode: self._ready_cache = None def set_field_ctype_complex_type( - self, name: str, ctype_complex_type: Any, mark_ready: bool = False + self, name: str, ctype_complex_type: Any, mark_ready: bool = False ) -> None: """Set a field's ctype_complex_type and optionally mark it as ready.""" if name not in self.fields: @@ -213,7 +213,7 @@ class DependencyNode: self._ready_cache = None def set_field_bitfield_size( - self, name: str, bitfield_size: Any, mark_ready: bool = False + self, name: str, bitfield_size: Any, mark_ready: bool = False ) -> None: """Set a field's bitfield_size and optionally mark it as ready.""" if name not in self.fields: @@ -224,10 +224,10 @@ class DependencyNode: self._ready_cache = None def set_field_ready( - self, - name: str, - is_ready: bool = False, - size_of_containing_type: Optional[int] = None, + self, + name: str, + is_ready: bool = False, + size_of_containing_type: Optional[int] = None, ) -> None: """Mark a field as ready or not ready.""" if name not in self.fields: @@ -242,7 +242,9 @@ class DependencyNode: except AttributeError: # Fallback to manual calculation if field not found in ctype_struct self.fields[name].set_offset(self.current_offset) - self.current_offset += self._calculate_size(name, size_of_containing_type) + self.current_offset += self._calculate_size( + name, size_of_containing_type + ) else: # Manual offset calculation when no ctype_struct is available self.fields[name].set_offset(self.current_offset) @@ -252,7 +254,7 @@ class DependencyNode: self._ready_cache = None def _calculate_size( - self, name: str, size_of_containing_type: Optional[int] = None + self, name: str, size_of_containing_type: Optional[int] = None ) -> int: processing_field = self.fields[name] # size_of_field will be in bytes @@ -264,12 +266,12 @@ class DependencyNode: if issubclass(processing_field.ctype_complex_type, ctypes.Array): if processing_field.containing_type.__module__ == ctypes.__name__: if ( - processing_field.containing_type is not None - and processing_field.type_size is not None + processing_field.containing_type is not None + and processing_field.type_size is not None ): size_of_field = ( - ctypes.sizeof(processing_field.containing_type) - * processing_field.type_size + ctypes.sizeof(processing_field.containing_type) + * processing_field.type_size ) else: raise RuntimeError( @@ -278,11 +280,11 @@ class DependencyNode: return size_of_field elif processing_field.containing_type.__module__ == "vmlinux": if ( - size_of_containing_type is not None - and processing_field.type_size is not None + size_of_containing_type is not None + and processing_field.type_size is not None ): size_of_field = ( - size_of_containing_type * processing_field.type_size + size_of_containing_type * processing_field.type_size ) else: raise RuntimeError( diff --git a/pythonbpf/vmlinux_parser/ir_gen/ir_generation.py b/pythonbpf/vmlinux_parser/ir_gen/ir_generation.py index 6c7d3e3..989a448 100644 --- a/pythonbpf/vmlinux_parser/ir_gen/ir_generation.py +++ b/pythonbpf/vmlinux_parser/ir_gen/ir_generation.py @@ -33,7 +33,9 @@ class IRGenerator: # Detect circular dependency if struct.name in processing_stack: - logger.info(f"Circular dependency detected for {struct.name}, skipping recursive processing") + logger.info( + f"Circular dependency detected for {struct.name}, skipping recursive processing" + ) # For circular dependencies, we can either: # 1. Use forward declarations (opaque pointers) # 2. Mark as incomplete and process later @@ -54,9 +56,13 @@ class IRGenerator: if dependency in self.handler.nodes: dep_node_from_dependency = self.handler[dependency] # Pass the processing_stack down to track circular refs - self.struct_processor(dep_node_from_dependency, processing_stack) + self.struct_processor( + dep_node_from_dependency, processing_stack + ) else: - raise RuntimeError(f"Warning: Dependency {dependency} not found in handler") + raise RuntimeError( + f"Warning: Dependency {dependency} not found in handler" + ) # Actual processor logic here after dependencies are resolved self.gen_ir(struct) @@ -74,13 +80,17 @@ class IRGenerator: field_index = 0 for field_name, field in struct.fields.items(): # does not take arrays and similar types into consideration yet. - if field.ctype_complex_type is not None and issubclass(field.ctype_complex_type, ctypes.Array): + if field.ctype_complex_type is not None and issubclass( + field.ctype_complex_type, ctypes.Array + ): array_size = field.type_size containing_type = field.containing_type if containing_type.__module__ == ctypes.__name__: containing_type_size = ctypes.sizeof(containing_type) - for i in range(0,array_size): - field_co_re_name = self._struct_name_generator(struct, field, field_index, True, i, containing_type_size) + for i in range(0, array_size): + field_co_re_name = self._struct_name_generator( + struct, field, field_index, True, i, containing_type_size + ) globvar = ir.GlobalVariable( self.llvm_module, ir.IntType(64), name=field_co_re_name ) @@ -91,9 +101,13 @@ class IRGenerator: array_size = field.type_size containing_type = field.containing_type if containing_type.__module__ == "vmlinux": - containing_type_size = self.handler[containing_type.__name__].current_offset - for i in range(0,array_size): - field_co_re_name = self._struct_name_generator(struct, field, field_index, True, i, containing_type_size) + containing_type_size = self.handler[ + containing_type.__name__ + ].current_offset + for i in range(0, array_size): + field_co_re_name = self._struct_name_generator( + struct, field, field_index, True, i, containing_type_size + ) globvar = ir.GlobalVariable( self.llvm_module, ir.IntType(64), name=field_co_re_name ) @@ -101,7 +115,9 @@ class IRGenerator: globvar.set_metadata("llvm.preserve.access.index", debug_info) field_index += 1 else: - field_co_re_name = self._struct_name_generator(struct, field, field_index) + field_co_re_name = self._struct_name_generator( + struct, field, field_index + ) field_index += 1 globvar = ir.GlobalVariable( self.llvm_module, ir.IntType(64), name=field_co_re_name @@ -110,15 +126,21 @@ class IRGenerator: globvar.set_metadata("llvm.preserve.access.index", debug_info) def _struct_name_generator( - self, struct: DependencyNode, field, field_index: int, is_indexed: bool=False, index: Optional[int]=None, containing_type_size: Optional[int]=None + self, + struct: DependencyNode, + field, + field_index: int, + is_indexed: bool = False, + index: int = 0, + containing_type_size: Optional[int] = None, ) -> str: if is_indexed: name = ( - "llvm." - + struct.name.removeprefix("struct_") - + f":0:{field.offset + index*containing_type_size}" - + "$" - + f"0:{field_index}:{index}" + "llvm." + + struct.name.removeprefix("struct_") + + f":0:{field.offset + index * containing_type_size}" + + "$" + + f"0:{field_index}:{index}" ) return name elif struct.name.startswith("struct_"): diff --git a/tests/failing_tests/xdp_pass.py b/tests/failing_tests/xdp_pass.py index 3354e75..595632b 100644 --- a/tests/failing_tests/xdp_pass.py +++ b/tests/failing_tests/xdp_pass.py @@ -3,7 +3,6 @@ from pythonbpf.maps import HashMap from pythonbpf.helper import XDP_PASS from vmlinux import TASK_COMM_LEN # noqa: F401 from vmlinux import struct_trace_event_raw_sys_enter # noqa: F401 -from vmlinux import struct_posix_cputimers from vmlinux import struct_xdp_md # from vmlinux import struct_trace_event_raw_sys_enter # noqa: F401 # from vmlinux import struct_ring_buffer_per_cpu # noqa: F401