|
5 | 5 | from llvmlite import ir |
6 | 6 | from pythonbpf.expr import eval_expr, convert |
7 | 7 | from pythonbpf.helper import emit_probe_read_kernel_str_call |
8 | | -from pythonbpf.type_deducer import ctypes_to_ir |
| 8 | +from pythonbpf.type_deducer import field_int_type |
9 | 9 | from pythonbpf.vmlinux_parser.dependency_node import Field |
10 | 10 |
|
11 | 11 | logger = logging.getLogger(__name__) |
@@ -40,6 +40,10 @@ def handle_struct_field_assignment( |
40 | 40 | return |
41 | 41 |
|
42 | 42 | val, val_type = val_result |
| 43 | + if isinstance(val_type, Field): |
| 44 | + field_ty = field_int_type(val_type) |
| 45 | + if field_ty is not None: |
| 46 | + val_type = field_ty |
43 | 47 |
|
44 | 48 | # Special case: i8* string to [N x i8] char array |
45 | 49 | if _is_char_array(field_type) and _is_i8_ptr(val_type): |
@@ -150,6 +154,13 @@ def handle_variable_assignment( |
150 | 154 | logger.info( |
151 | 155 | f"Evaluated value for {var_name}: {val} of type {val_type}, expected {var_type}" |
152 | 156 | ) |
| 157 | + # An integer vmlinux field is, for conversion purposes, its declared IntTy |
| 158 | + # (width and sign from the ctype), so it takes the same convert() path as |
| 159 | + # every other integer below instead of a special case. |
| 160 | + if isinstance(val_type, Field): |
| 161 | + field_ty = field_int_type(val_type) |
| 162 | + if field_ty is not None: |
| 163 | + val_type = field_ty |
153 | 164 |
|
154 | 165 | if isinstance(val_type, ir.IntType) and isinstance(var_type, ir.IntType): |
155 | 166 | # The descriptor may be narrower than the constant carrying the value |
@@ -194,33 +205,13 @@ def handle_variable_assignment( |
194 | 205 | ) |
195 | 206 | return False |
196 | 207 | if isinstance(val_type, Field): |
197 | | - logger.info("Handling assignment to struct field") |
198 | | - field_ir_type = ctypes_to_ir(val_type.type.__name__) |
199 | | - # Sub-register-width context fields are zero-extended to i64 by |
200 | | - # load_ctx_field, so val is already i64 even though the field type |
201 | | - # says otherwise (c_uint for xdp_md, c_ushort for pt_regs.cs/ss). |
202 | | - if ( |
203 | | - isinstance(field_ir_type, ir.IntType) |
204 | | - and field_ir_type.width < 64 |
205 | | - and isinstance(var_type, ir.IntType) |
206 | | - and var_type.width == 64 |
207 | | - ): |
208 | | - builder.store(val, var_ptr) |
209 | | - logger.info( |
210 | | - f"Assigned zero-extended i{field_ir_type.width} context field " |
211 | | - f"to {var_name} (i64)" |
212 | | - ) |
213 | | - return True |
214 | | - # TODO: handling only ctype struct fields for now. Handle other stuff too later. |
215 | | - elif var_type == field_ir_type: |
216 | | - builder.store(val, var_ptr) |
217 | | - logger.info(f"Assigned ctype struct field to {var_name}") |
218 | | - return True |
219 | | - else: |
220 | | - logger.error( |
221 | | - f"Failed to assign ctype struct field to {var_name}: {val_type} != {var_type}" |
222 | | - ) |
223 | | - return False |
| 208 | + # Integer fields were normalised to their IntTy above; what is |
| 209 | + # left is a pointer, array or struct field, which has no path |
| 210 | + # into this slot. |
| 211 | + logger.error( |
| 212 | + f"Failed to assign ctype struct field to {var_name}: {val_type} != {var_type}" |
| 213 | + ) |
| 214 | + return False |
224 | 215 | elif isinstance(val_type, ir.IntType) and isinstance(var_type, ir.PointerType): |
225 | 216 | # NOTE: This is assignment to a PTR_TO_MAP_VALUE_OR_NULL |
226 | 217 | logger.info( |
|
0 commit comments