@@ -73,17 +73,6 @@ def get_vmlinux_enum_value(self, name):
7373 return value
7474 return None
7575
76- def handle_vmlinux_struct (self , struct_name , module , builder ):
77- """Handle vmlinux struct initializations"""
78- if self .is_vmlinux_struct (struct_name ):
79- # TODO: Implement core-specific struct handling
80- # This will be more complex and depends on the BTF information
81- logger .info (f"Handling vmlinux struct { struct_name } " )
82- # Return struct type and allocated pointer
83- # This is a stub, actual implementation will be more complex
84- return None
85- return None
86-
8776 def handle_vmlinux_struct_field (
8877 self , struct_var_name , field_name , module , builder , local_sym_tab
8978 ):
@@ -97,26 +86,82 @@ def handle_vmlinux_struct_field(
9786 globvar_ir , field_data = self .get_field_type (
9887 python_type .__name__ , field_name
9988 )
89+ builder .function .args [0 ].type = ir .PointerType (ir .IntType (8 ))
90+ print (builder .function .args [0 ])
91+ field_ptr = self .load_ctx_field (builder , builder .function .args [0 ], globvar_ir )
92+ print (field_ptr )
93+ # Return pointer to field and field type
94+ return field_ptr , field_data
95+ else :
96+ raise RuntimeError ("Variable accessed not found in symbol table" )
10097
101- # Load the offset value
102- offset = builder .load (globvar_ir )
98+ @staticmethod
99+ def load_ctx_field (builder , ctx_arg , offset_global ):
100+ """
101+ Generate LLVM IR to load a field from BPF context using offset.
103102
104- # Convert pointer to integer
105- i64_type = ir .IntType (64 )
106- ptr_as_int = builder .ptrtoint (var_info .var , i64_type )
103+ Args:
104+ builder: llvmlite IRBuilder instance
105+ ctx_arg: The context pointer argument (ptr/i8*)
106+ offset_global: Global variable containing the field offset (i64)
107107
108- # Add the offset
109- field_addr = builder .add (ptr_as_int , offset )
108+ Returns:
109+ The loaded value (i64 register)
110+ """
110111
111- # Convert back to pointer
112- i8_ptr_type = ir .IntType (8 ).as_pointer ()
113- field_ptr_i8 = builder .inttoptr (field_addr , i8_ptr_type )
114- logger .info (f"field_ptr_i8: { field_ptr_i8 } " )
112+ # Load the offset value
113+ offset = builder .load (offset_global )
115114
116- # Return pointer to field and field type
117- return field_ptr_i8 , field_data
115+ # Ensure ctx_arg is treated as i8* (byte pointer)
116+ i8_type = ir .IntType (8 )
117+ i8_ptr_type = ir .PointerType (i8_type )
118+
119+ # Cast ctx_arg to i8* if it isn't already
120+ if str (ctx_arg .type ) != str (i8_ptr_type ):
121+ ctx_i8_ptr = builder .bitcast (ctx_arg , i8_ptr_type )
118122 else :
119- raise RuntimeError ("Variable accessed not found in symbol table" )
123+ ctx_i8_ptr = ctx_arg
124+
125+ # GEP with explicit type - this is the key fix
126+ field_ptr = builder .gep (
127+ ctx_i8_ptr ,
128+ [offset ],
129+ inbounds = False ,
130+ )
131+
132+ # Get or declare the BPF passthrough intrinsic
133+ module = builder .function .module
134+
135+ try :
136+ passthrough_fn = module .globals .get ('llvm.bpf.passthrough.p0.p0' )
137+ if passthrough_fn is None :
138+ raise KeyError
139+ except (KeyError , AttributeError ):
140+ passthrough_type = ir .FunctionType (
141+ i8_ptr_type ,
142+ [ir .IntType (32 ), i8_ptr_type ]
143+ )
144+ passthrough_fn = ir .Function (
145+ module ,
146+ passthrough_type ,
147+ name = 'llvm.bpf.passthrough.p0.p0'
148+ )
149+
150+ # Call passthrough to satisfy BPF verifier
151+ verified_ptr = builder .call (
152+ passthrough_fn ,
153+ [ir .Constant (ir .IntType (32 ), 0 ), field_ptr ],
154+ )
155+
156+ # Bitcast to i64* (assuming field is 64-bit, adjust if needed)
157+ i64_ptr_type = ir .PointerType (ir .IntType (64 ))
158+ typed_ptr = builder .bitcast (verified_ptr , i64_ptr_type )
159+
160+ # Load and return the value
161+ value = builder .load (typed_ptr )
162+
163+ return value
164+
120165
121166 def has_field (self , struct_name , field_name ):
122167 """Check if a vmlinux struct has a specific field"""
0 commit comments