Skip to content

Commit 64674cf

Browse files
add alloc for only i64
1 parent 36a1a09 commit 64674cf

File tree

7 files changed

+79
-20
lines changed

7 files changed

+79
-20
lines changed

pythonbpf/allocation_pass.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import ast
2+
import ctypes
23
import logging
34

45
from llvmlite import ir
56
from dataclasses import dataclass
67
from typing import Any
78
from pythonbpf.helper import HelperHandlerRegistry
9+
from pythonbpf.vmlinux_parser.dependency_node import Field
810
from .expr import VmlinuxHandlerRegistry
911
from pythonbpf.type_deducer import ctypes_to_ir
1012

@@ -60,21 +62,11 @@ def handle_assign_allocation(builder, stmt, local_sym_tab, structs_sym_tab):
6062
continue
6163

6264
var_name = target.id
63-
6465
# Skip if already allocated
6566
if var_name in local_sym_tab:
6667
logger.debug(f"Variable {var_name} already allocated, skipping")
6768
continue
6869

69-
# When allocating a variable, check if it's a vmlinux struct type
70-
if isinstance(
71-
stmt.value, ast.Name
72-
) and VmlinuxHandlerRegistry.is_vmlinux_struct(stmt.value.id):
73-
# Handle vmlinux struct allocation
74-
# This requires more implementation
75-
print(stmt.value)
76-
pass
77-
7870
# Determine type and allocate based on rval
7971
if isinstance(rval, ast.Call):
8072
_allocate_for_call(builder, var_name, rval, local_sym_tab, structs_sym_tab)
@@ -248,9 +240,40 @@ def _allocate_for_attribute(builder, var_name, rval, local_sym_tab, structs_sym_
248240
logger.error(f"Struct variable '{struct_var}' not found")
249241
return
250242

251-
struct_type = local_sym_tab[struct_var].metadata
243+
struct_type: type = local_sym_tab[struct_var].metadata
252244
if not struct_type or struct_type not in structs_sym_tab:
253-
logger.error(f"Struct type '{struct_type}' not found")
245+
if VmlinuxHandlerRegistry.is_vmlinux_struct(struct_type.__name__):
246+
# Handle vmlinux struct field access
247+
vmlinux_struct_name = struct_type.__name__
248+
if not VmlinuxHandlerRegistry.has_field(vmlinux_struct_name, field_name):
249+
logger.error(f"Field '{field_name}' not found in vmlinux struct '{vmlinux_struct_name}'")
250+
return
251+
252+
field_type: tuple[ir.GlobalVariable, Field] = VmlinuxHandlerRegistry.get_field_type(vmlinux_struct_name, field_name)
253+
field_ir, field = field_type
254+
#TODO: For now, we only support integer type allocations.
255+
256+
# loaded_value = builder.load(field_ir, align=8)
257+
# #TODO: fatal flaw that this always assumes first argument of function to be the context of what this gets.
258+
# base_ptr = builder.function.args[0]
259+
# gep_result = builder.gep(
260+
# base_ptr,
261+
# [loaded_value],
262+
# inbounds=False, # Not using inbounds GEP
263+
# )
264+
# print("DEBB", loaded_value, base_ptr, gep_result)
265+
# Use i64 for allocation since that's what the global variable contains
266+
267+
actual_ir_type = ir.IntType(64)
268+
269+
# Allocate with the actual IR type, not the GlobalVariable
270+
var = _allocate_with_type(builder, var_name, actual_ir_type)
271+
local_sym_tab[var_name] = LocalSymbol(var, actual_ir_type, field)
272+
273+
logger.info(f"Pre-allocated {var_name} from vmlinux struct {vmlinux_struct_name}.{field_name}")
274+
return
275+
else:
276+
logger.error(f"Struct type '{struct_type}' not found")
254277
return
255278

256279
struct_info = structs_sym_tab[struct_type]

pythonbpf/expr/vmlinux_registry.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,18 @@ def get_struct_type(cls, name):
5252
if cls._handler is None:
5353
return None
5454
return cls._handler.get_vmlinux_struct_type(name)
55+
56+
@classmethod
57+
def has_field(cls, vmlinux_struct_name, field_name):
58+
"""Check if a vmlinux struct has a specific field"""
59+
if cls._handler is None:
60+
return False
61+
return cls._handler.has_field(vmlinux_struct_name, field_name)
62+
63+
@classmethod
64+
def get_field_type(cls, vmlinux_struct_name, field_name):
65+
"""Get the type of a field in a vmlinux struct"""
66+
if cls._handler is None:
67+
return None
68+
assert isinstance(cls._handler, VmlinuxHandler)
69+
return cls._handler.get_field_type(vmlinux_struct_name, field_name)

pythonbpf/functions/functions_pass.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from pythonbpf.allocation_pass import (
2121
handle_assign_allocation,
2222
allocate_temp_pool,
23-
create_targets_and_rvals,
23+
create_targets_and_rvals, LocalSymbol,
2424
)
2525

2626
from .return_utils import handle_none_return, handle_xdp_return, is_xdp_name
@@ -347,11 +347,12 @@ def process_func_body(
347347
resolved_type = VmlinuxHandlerRegistry.get_struct_type(
348348
context_type_name
349349
)
350-
context_type = {"type": ir.PointerType(resolved_type), "ptr": True}
350+
context_type = LocalSymbol(None, ir.PointerType(resolved_type), resolved_type)
351351
else:
352352
try:
353353
resolved_type = ctypes_to_ir(context_type_name)
354-
context_type = {"type": ir.PointerType(resolved_type), "ptr": True}
354+
logger.error("THIS SHOULD NOT HAPPEN. I THINK. PROBABLY.")
355+
context_type = LocalSymbol(None, ir.PointerType(resolved_type), resolved_type)
355356
except Exception:
356357
raise TypeError(f"Type '{context_type_name}' not declared")
357358

pythonbpf/vmlinux_parser/vmlinux_exports_handler.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,23 @@ def handle_vmlinux_struct_field(
9898
# Return pointer to field and field type
9999
return None
100100
return None
101+
102+
def has_field(self, struct_name, field_name):
103+
"""Check if a vmlinux struct has a specific field"""
104+
if self.is_vmlinux_struct(struct_name):
105+
python_type = self.vmlinux_symtab[struct_name]["python_type"]
106+
return hasattr(python_type, field_name)
107+
return False
108+
109+
def get_field_type(self, vmlinux_struct_name, field_name):
110+
"""Get the type of a field in a vmlinux struct"""
111+
if self.is_vmlinux_struct(vmlinux_struct_name):
112+
python_type = self.vmlinux_symtab[vmlinux_struct_name]["python_type"]
113+
if hasattr(python_type, field_name):
114+
return self.vmlinux_symtab[vmlinux_struct_name]["members"][field_name]
115+
else:
116+
raise ValueError(
117+
f"Field {field_name} not found in vmlinux struct {vmlinux_struct_name}"
118+
)
119+
else:
120+
raise ValueError(f"{vmlinux_struct_name} is not a vmlinux struct")

tests/c-form/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
BPF_CLANG := clang
2-
CFLAGS := -O2 -emit-llvm -target bpf -c
2+
CFLAGS := -O0 -emit-llvm -target bpf -c
33

44
SRC := $(wildcard *.bpf.c)
55
LL := $(SRC:.bpf.c=.bpf.ll)

tests/failing_tests/vmlinux/struct_field_access.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def hello_world(ctx: struct_trace_event_raw_sys_enter) -> c_int64:
1717
a = 2 + TASK_COMM_LEN + TASK_COMM_LEN
1818
b = ctx.id
1919
print(f"Hello, World{TASK_COMM_LEN} and {a}")
20-
print(f"This is context field {b}")
20+
# print(f"This is context field {b}")
2121
return c_int64(TASK_COMM_LEN + 2)
2222

2323

tests/passing_tests/assign/comprehensive.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from pythonbpf import bpf, map, section, bpfglobal, compile, struct
1+
from pythonbpf import bpf, map, section, bpfglobal, compile, struct, compile_to_ir
22
from ctypes import c_void_p, c_int64, c_int32, c_uint64
33
from pythonbpf.maps import HashMap
44
from pythonbpf.helper import ktime
@@ -70,5 +70,5 @@ def hello_world(ctx: c_void_p) -> c_int64:
7070
def LICENSE() -> str:
7171
return "GPL"
7272

73-
74-
compile()
73+
compile_to_ir("comprehensive.py", "comprehensive.ll")
74+
# compile()

0 commit comments

Comments
 (0)