diff --git a/pythonbpf/helper/bpf_helper_handler.py b/pythonbpf/helper/bpf_helper_handler.py index 196c9d9..362bb41 100644 --- a/pythonbpf/helper/bpf_helper_handler.py +++ b/pythonbpf/helper/bpf_helper_handler.py @@ -10,6 +10,7 @@ from .helper_utils import ( get_buffer_ptr_and_size, get_char_array_ptr_and_size, get_ptr_from_arg, + get_int_value_from_arg, ) from .printk_formatter import simple_string_print, handle_fstring_print @@ -457,6 +458,64 @@ def bpf_get_prandom_u32_emitter( return result, ir.IntType(32) +@HelperHandlerRegistry.register("probe_read") +def bpf_probe_read_emitter( + call, + map_ptr, + module, + builder, + func, + local_sym_tab=None, + struct_sym_tab=None, + map_sym_tab=None, +): + """ + Emit LLVM IR for bpf_probe_read helper function + """ + + if len(call.args) != 3: + logger.warn("Expected 3 args for probe_read helper") + return + dst_ptr, _ = get_ptr_from_arg( + call.args[0], func, module, builder, local_sym_tab, map_sym_tab, struct_sym_tab + ) + size_val = ( + get_int_value_from_arg( + call.args[1], + func, + module, + builder, + local_sym_tab, + map_sym_tab, + struct_sym_tab, + ) + & 0xFFFFFFFF + ) + src_ptr, _ = get_ptr_from_arg( + call.args[2], func, module, builder, local_sym_tab, map_sym_tab, struct_sym_tab + ) + fn_type = ir.FunctionType( + ir.IntType(64), + [ir.PointerType(), ir.IntType(32), ir.PointerType()], + var_arg=False, + ) + fn_ptr = builder.inttoptr( + ir.Constant(ir.IntType(64), BPFHelperID.BPF_PROBE_READ.value), + ir.PointerType(fn_type), + ) + result = builder.call( + fn_ptr, + [ + builder.bitcast(dst_ptr, ir.PointerType()), + ir.Constant(ir.IntType(32), size_val), + builder.bitcast(src_ptr, ir.PointerType()), + ], + tail=False, + ) + logger.info(f"Emitted bpf_probe_read (size={size_val})") + return result, ir.IntType(64) + + def handle_helper_call( call, module, diff --git a/pythonbpf/helper/helper_utils.py b/pythonbpf/helper/helper_utils.py index fdfd452..841698c 100644 --- a/pythonbpf/helper/helper_utils.py +++ b/pythonbpf/helper/helper_utils.py @@ -274,3 +274,23 @@ def get_ptr_from_arg( raise ValueError(f"Expected pointer type, got {val_type}") return val, val_type + + +def get_int_value_from_arg( + arg, func, module, builder, local_sym_tab, map_sym_tab, struct_sym_tab +): + """Evaluate argument and return integer value""" + + result = eval_expr( + func, module, builder, arg, local_sym_tab, map_sym_tab, struct_sym_tab + ) + + if not result: + raise ValueError("Failed to evaluate argument") + + val, val_type = result + + if not isinstance(val_type, ir.IntType): + raise ValueError(f"Expected integer type, got {val_type}") + + return val