From fefd6840c88fc8c50d723ce3316d04d0c63e12be Mon Sep 17 00:00:00 2001 From: Pragyansh Chaturvedi Date: Sun, 21 Sep 2025 17:50:58 +0530 Subject: [PATCH] finish perf_event_output helper integration --- pythonbpf/bpf_helper_handler.py | 37 +++++++++++++++++++++++++++------ pythonbpf/structs_pass.py | 20 +++++++++++++++++- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/pythonbpf/bpf_helper_handler.py b/pythonbpf/bpf_helper_handler.py index 95a8639..36297a6 100644 --- a/pythonbpf/bpf_helper_handler.py +++ b/pythonbpf/bpf_helper_handler.py @@ -359,12 +359,37 @@ def bpf_perf_event_output_handler(call, map_ptr, module, builder, func, local_sy data_type = local_var_metadata[data_name] if data_type in struct_sym_tab: struct_info = struct_sym_tab[data_type] - data_size = 0 - for field_type in struct_info["type"].elements: - if isinstance(field_type, ir.IntType): - data_size += field_type.width // 8 - elif isinstance(field_type, ir.PointerType): - data_size += 8 + size_val = ir.Constant(ir.IntType(64), struct_info["size"]) + else: + raise ValueError( + f"Struct type {data_type} for variable {data_name} not found in struct symbol table.") + else: + raise ValueError( + f"Metadata for variable {data_name} not found in local variable metadata.") + + # BPF_F_CURRENT_CPU is 0 + flags_val = ir.Constant(ir.IntType(64), 0) + + map_void_ptr = builder.bitcast(map_ptr, ir.PointerType()) + data_void_ptr = builder.bitcast(data_ptr, ir.PointerType()) + fn_type = ir.FunctionType( + ir.IntType(64), + [ir.PointerType(ir.IntType(8)), ir.PointerType(), ir.IntType(64), + ir.PointerType(), ir.IntType(64)], + var_arg=False + ) + fn_ptr_type = ir.PointerType(fn_type) + + # helper id + fn_addr = ir.Constant(ir.IntType(64), 25) + fn_ptr = builder.inttoptr(fn_addr, fn_ptr_type) + + result = builder.call( + fn_ptr, [ctx_ptr, map_void_ptr, flags_val, data_void_ptr, size_val], tail=False) + return result + else: + raise NotImplementedError( + "Only simple object names are supported as data in perf event output.") helper_func_list = { diff --git a/pythonbpf/structs_pass.py b/pythonbpf/structs_pass.py index 6574af0..fbe06ed 100644 --- a/pythonbpf/structs_pass.py +++ b/pythonbpf/structs_pass.py @@ -31,9 +31,27 @@ def process_bpf_struct(cls_node, module): field_names.append(item.target.id) field_types.append(ctypes_to_ir(item.annotation.id)) + curr_offset = 0 + for ftype in field_types: + if isinstance(ftype, ir.IntType): + fsize = ftype.width // 8 + alignment = fsize + elif isinstance(ftype, ir.PointerType): + fsize = 8 + alignment = 8 + else: + print(f"Unsupported field type in struct {struct_name}") + return + padding = (alignment - (curr_offset % alignment)) % alignment + curr_offset += padding + curr_offset += fsize + final_padding = (8 - (curr_offset % 8)) % 8 + total_size = curr_offset + final_padding + struct_type = ir.LiteralStructType(field_types) structs_sym_tab[struct_name] = { "type": struct_type, - "fields": {name: idx for idx, name in enumerate(field_names)} + "fields": {name: idx for idx, name in enumerate(field_names)}, + "size": total_size } print(f"Created struct {struct_name} with fields {field_names}")