Skip to content

Commit a4cfc2b

Browse files
add assignments table and offset handler
1 parent 69b7300 commit a4cfc2b

File tree

5 files changed

+62
-13
lines changed

5 files changed

+62
-13
lines changed

pythonbpf/vmlinux_parser/class_handler.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ def process_vmlinux_post_ast(
7171
if len(field_elem) == 2:
7272
field_name, field_type = field_elem
7373
elif len(field_elem) == 3:
74-
raise NotImplementedError("Bitfields are not supported in the current version")
74+
raise NotImplementedError(
75+
"Bitfields are not supported in the current version"
76+
)
7577
field_name, field_type, bitfield_size = field_elem
7678
field_table[field_name] = [field_type, bitfield_size]
7779
elif hasattr(class_obj, "__annotations__"):
@@ -145,7 +147,8 @@ def process_vmlinux_post_ast(
145147
process_vmlinux_post_ast(
146148
containing_type, llvm_handler, handler, processing_stack
147149
)
148-
new_dep_node.set_field_ready(elem_name, True)
150+
size_of_containing_type = (handler[containing_type.__name__]).__sizeof__()
151+
new_dep_node.set_field_ready(elem_name, True, size_of_containing_type)
149152
elif containing_type.__module__ == ctypes.__name__:
150153
logger.debug(f"Processing ctype internal{containing_type}")
151154
new_dep_node.set_field_ready(elem_name, True)
@@ -162,7 +165,8 @@ def process_vmlinux_post_ast(
162165
process_vmlinux_post_ast(
163166
elem_type, llvm_handler, handler, processing_stack
164167
)
165-
new_dep_node.set_field_ready(elem_name, True)
168+
size_of_containing_type = (handler[elem_type.__name__]).__sizeof__()
169+
new_dep_node.set_field_ready(elem_name, True, size_of_containing_type)
166170
else:
167171
raise ValueError(
168172
f"{elem_name} with type {elem_type} from module {module_name} not supported in recursive resolver"

pythonbpf/vmlinux_parser/dependency_node.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from dataclasses import dataclass, field
22
from typing import Dict, Any, Optional
3+
import ctypes
34

45

56
# TODO: FIX THE FUCKING TYPE NAME CONVENTION.
@@ -140,11 +141,14 @@ def add_field(
140141
type_size=type_size,
141142
ctype_complex_type=ctype_complex_type,
142143
bitfield_size=bitfield_size,
143-
offset=offset
144+
offset=offset,
144145
)
145146
# Invalidate readiness cache
146147
self._ready_cache = None
147148

149+
def __sizeof__(self):
150+
return self.current_offset
151+
148152
def get_field(self, name: str) -> Field:
149153
"""Get a field by name."""
150154
return self.fields[name]
@@ -211,20 +215,53 @@ def set_field_bitfield_size(
211215
# Invalidate readiness cache
212216
self._ready_cache = None
213217

214-
def set_field_ready(self, name: str, is_ready: bool = False) -> None:
218+
def set_field_ready(self, name: str, is_ready: bool = False, size_of_containing_type: Optional[int] = None) -> None:
215219
"""Mark a field as ready or not ready."""
216220
if name not in self.fields:
217221
raise KeyError(f"Field '{name}' does not exist in node '{self.name}'")
218222

219223
self.fields[name].set_ready(is_ready)
220224
self.fields[name].set_offset(self.current_offset)
221-
self.current_offset += self._calculate_size(name)
222-
225+
self.current_offset += self._calculate_size(name, size_of_containing_type)
223226
# Invalidate readiness cache
224227
self._ready_cache = None
225228

226-
def _calculate_size(self, name: str) -> int:
227-
pass
229+
def _calculate_size(self, name: str, size_of_containing_type: Optional[int] = None) -> int:
230+
processing_field = self.fields[name]
231+
# size_of_field will be in bytes
232+
if processing_field.type.__module__ == ctypes.__name__:
233+
size_of_field = ctypes.sizeof(processing_field.type)
234+
return size_of_field
235+
elif processing_field.type.__module__ == "vmlinux":
236+
size_of_field: int = 0
237+
if processing_field.ctype_complex_type is not None:
238+
if issubclass(processing_field.ctype_complex_type, ctypes.Array):
239+
if processing_field.containing_type.__module__ == ctypes.__name__:
240+
size_of_field = (
241+
ctypes.sizeof(processing_field.containing_type)
242+
* processing_field.type_size
243+
)
244+
return size_of_field
245+
elif processing_field.containing_type.__module__ == "vmlinux":
246+
size_of_field = (
247+
size_of_containing_type
248+
* processing_field.type_size
249+
)
250+
return size_of_field
251+
elif issubclass(processing_field.ctype_complex_type, ctypes._Pointer):
252+
return ctypes.sizeof(ctypes.pointer())
253+
else:
254+
raise NotImplementedError(
255+
"This subclass of ctype not supported yet"
256+
)
257+
else:
258+
# search up pre-created stuff and get size
259+
return size_of_containing_type
260+
261+
else:
262+
raise ModuleNotFoundError("Module is not supported for the operation")
263+
raise RuntimeError("control should not reach here")
264+
228265
@property
229266
def is_ready(self) -> bool:
230267
"""Check if the node is ready (all fields are ready)."""

pythonbpf/vmlinux_parser/import_detector.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,13 @@ def vmlinux_proc(tree: ast.AST, module):
129129
)
130130

131131
IRGenerator(module, handler)
132+
return assignments
132133

133134

134135
def process_vmlinux_assign(node, module, assignments: Dict[str, type]):
135-
raise NotImplementedError("Assignment handling has not been implemented yet")
136+
# Check if this is a simple assignment with a constant value
137+
if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name):
138+
target_name = node.targets[0].id
139+
if isinstance(node.value, ast.Constant):
140+
assignments[target_name] = node.value.value
141+
logger.info(f"Added assignment: {target_name} = {node.value.value}")

pythonbpf/vmlinux_parser/ir_gen/ir_generation.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def struct_processor(self, struct):
3030
# this part cannot yet resolve circular dependencies. Gets stuck on an infinite loop during that.
3131
self.generated.append(struct.name)
3232

33-
34-
def struct_name_generator(self, ):
33+
def struct_name_generator(
34+
self,
35+
) -> None:
3536
pass

tests/failing_tests/xdp_pass.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from pythonbpf import bpf, map, section, bpfglobal, compile_to_ir
22
from pythonbpf.maps import HashMap
33
from pythonbpf.helper import XDP_PASS
4+
from vmlinux import TASK_COMM_LEN # noqa: F401
5+
from vmlinux import struct_trace_event_raw_sys_enter # noqa: F401
46
# from vmlinux import struct_request
5-
from vmlinux import struct_trace_event_raw_sys_enter
67
from vmlinux import struct_xdp_md
78
# from vmlinux import struct_trace_event_raw_sys_enter # noqa: F401
89
# from vmlinux import struct_ring_buffer_per_cpu # noqa: F401

0 commit comments

Comments
 (0)