From f7aa054b3158177e2388e5194c1b2b480762f3b2 Mon Sep 17 00:00:00 2001 From: varun-r-mallya Date: Mon, 8 Sep 2025 22:26:16 +0530 Subject: [PATCH] get hashmap compiling --- examples/c-form/Makefile | 2 +- examples/c-form/ex2.bpf.c | 10 ++++- pythonbpf/maps_pass.py | 94 +++++++++++++++++++-------------------- 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/examples/c-form/Makefile b/examples/c-form/Makefile index 5ae1f8f..6be0827 100644 --- a/examples/c-form/Makefile +++ b/examples/c-form/Makefile @@ -13,7 +13,7 @@ all: $(LL) $(OBJ) $(BPF_CLANG) -O2 -g -target bpf -c $< -o $@ %.bpf.ll: %.bpf.c - $(BPF_CLANG) $(CFLAGS) -S $< -o $@ + $(BPF_CLANG) $(CFLAGS) -g -S $< -o $@ clean: rm -f $(LL) $(OBJ) diff --git a/examples/c-form/ex2.bpf.c b/examples/c-form/ex2.bpf.c index f708248..e792e7f 100644 --- a/examples/c-form/ex2.bpf.c +++ b/examples/c-form/ex2.bpf.c @@ -1,13 +1,21 @@ #include #include #define u64 unsigned long long +#define u32 unsigned int + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, u32); + __type(value, u64); +} last SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 1); __type(key, u64); __type(value, u64); -} last SEC(".maps"); +} last2 SEC(".maps"); SEC("tracepoint/syscalls/sys_enter_execve") int hello(struct pt_regs *ctx) { diff --git a/pythonbpf/maps_pass.py b/pythonbpf/maps_pass.py index b8d5d6d..2de5b3b 100644 --- a/pythonbpf/maps_pass.py +++ b/pythonbpf/maps_pass.py @@ -18,39 +18,56 @@ def maps_proc(tree, module, chunks): def create_bpf_map(module, map_name, map_params): """Create a BPF map in the module with the given parameters""" - - key_type_str = map_params.get('key_type', 'c_uint32') - value_type_str = map_params.get('value_type', 'c_uint32') - - key_type = ctypes_to_ir(key_type_str) - value_type = ctypes_to_ir(value_type_str) - + + # Create the anonymous struct type for BPF map map_struct_type = ir.LiteralStructType([ - ir.PointerType(), # type - ir.PointerType(), # max_entries - ir.PointerType(), # key_type - ir.PointerType() # value_type + ir.PointerType(), + ir.PointerType(), + ir.PointerType(), + ir.PointerType() ]) - + + # Create the global variable map_global = ir.GlobalVariable(module, map_struct_type, name=map_name) - map_global.linkage = 'external' - map_global.initializer = ir.Constant( # type: ignore - map_struct_type, [None, None, None, None]) + map_global.linkage = 'dso_local' + map_global.global_constant = False + + # Initialize with zeroinitializer (all null pointers) + map_global.initializer = ir.Constant(map_struct_type, None) #type: ignore + map_global.section = ".maps" - map_global.align = 8 # type: ignore - - # TODO: Store map parameters in metadata or a suitable structure - # maps[map_name] = { - # 'global': map_global, - # 'key_type': key_type, - # 'value_type': value_type, - # 'max_entries': map_params.get('max_entries', 1), - # 'map_type': map_params.get('map_type', 'BPF_MAP_TYPE_HASH') - # } + map_global.align = 8 # type: ignore print(f"Created BPF map: {map_name}") return map_global +def process_hash_map(map_name, rval, module): + print(f"Creating HashMap map: {map_name}") + map_params: dict[str, object] = {"map_type": "HASH"} + + # Assuming order: key_type, value_type, max_entries + if len(rval.args) >= 1 and isinstance(rval.args[0], ast.Name): + map_params["key_type"] = rval.args[0].id + if len(rval.args) >= 2 and isinstance(rval.args[1], ast.Name): + map_params["value_type"] = rval.args[1].id + if len(rval.args) >= 3 and isinstance(rval.args[2], ast.Constant): + const_val = rval.args[2].value + if isinstance(const_val, (int, str)): # safe check + map_params["max_entries"] = const_val + + for keyword in rval.keywords: + if keyword.arg == "key_type" and isinstance(keyword.value, ast.Name): + map_params["key_type"] = keyword.value.id + elif keyword.arg == "value_type" and isinstance(keyword.value, ast.Name): + map_params["value_type"] = keyword.value.id + elif keyword.arg == "max_entries" and isinstance(keyword.value, ast.Constant): + const_val = keyword.value.value + if isinstance(const_val, (int, str)): + map_params["max_entries"] = const_val + + print(f"Map parameters: {map_params}") + return create_bpf_map(module, map_name, map_params) + def process_bpf_map(func_node, module): """Process a BPF map (a function decorated with @map)""" @@ -68,27 +85,8 @@ def process_bpf_map(func_node, module): rval = return_stmt.value - # For now, just handle maps + # Handle only HashMap maps if isinstance(rval, ast.Call) and isinstance(rval.func, ast.Name) and rval.func.id == "HashMap": - print(f"Creating HashMap map: {map_name}") - map_params = {'map_type': 'HASH'} - # Handle positional arguments - if rval.args: - # Assuming order is: key_type, value_type, max_entries - if len(rval.args) >= 1 and isinstance(rval.args[0], ast.Name): - map_params['key_type'] = rval.args[0].id - if len(rval.args) >= 2 and isinstance(rval.args[1], ast.Name): - map_params['value_type'] = rval.args[1].id - if len(rval.args) >= 3 and isinstance(rval.args[2], ast.Constant): - map_params['max_entries'] = rval.args[2].value - - # Handle keyword arguments (these will override any positional args) - for keyword in rval.keywords: - if keyword.arg == "key_type" and isinstance(keyword.value, ast.Name): - map_params['key_type'] = keyword.value.id - elif keyword.arg == "value_type" and isinstance(keyword.value, ast.Name): - map_params['value_type'] = keyword.value.id - elif keyword.arg == "max_entries" and isinstance(keyword.value, ast.Constant): - map_params['max_entries'] = keyword.value.value - print(f"Map parameters: {map_params}") - print(create_bpf_map(module, map_name, map_params)) + process_hash_map(map_name, rval, module) + else: + raise ValueError("Function under @map must return a map")