diff --git a/pythonbpf/maps/maps_pass.py b/pythonbpf/maps/maps_pass.py index 3a07c38..26f2aee 100644 --- a/pythonbpf/maps/maps_pass.py +++ b/pythonbpf/maps/maps_pass.py @@ -1,11 +1,12 @@ import ast +from logging import Logger from llvmlite import ir from enum import Enum from .maps_utils import MapProcessorRegistry from ..debuginfo import DebugInfoGenerator import logging -logger = logging.getLogger(__name__) +logger: Logger = logging.getLogger(__name__) def maps_proc(tree, module, chunks): @@ -13,7 +14,7 @@ def maps_proc(tree, module, chunks): map_sym_tab = {} for func_node in chunks: if is_map(func_node): - print(f"Found BPF map: {func_node.name}") + logger.info(f"Found BPF map: {func_node.name}") map_sym_tab[func_node.name] = process_bpf_map(func_node, module) return map_sym_tab @@ -145,6 +146,60 @@ def create_map_debug_info(module, map_global, map_name, map_params): return global_var +def create_ringbuf_debug_info(module, map_global, map_name, map_params): + """Generate debug information metadata for BPF RINGBUF map""" + generator = DebugInfoGenerator(module) + + int_type = generator.get_int32_type() + + type_array = generator.create_array_type( + int_type, map_params.get("type", BPFMapType.RINGBUF).value + ) + type_ptr = generator.create_pointer_type(type_array, 64) + type_member = generator.create_struct_member("type", type_ptr, 0) + + max_entries_array = generator.create_array_type(int_type, map_params["max_entries"]) + max_entries_ptr = generator.create_pointer_type(max_entries_array, 64) + max_entries_member = generator.create_struct_member( + "max_entries", max_entries_ptr, 64 + ) + + elements_arr = [type_member, max_entries_member] + + struct_type = generator.create_struct_type(elements_arr, 128, is_distinct=True) + + global_var = generator.create_global_var_debug_info( + map_name, struct_type, is_local=False + ) + map_global.set_metadata("dbg", global_var) + return global_var + + +@MapProcessorRegistry.register("RingBuf") +def process_ringbuf_map(map_name, rval, module): + """Process a BPF_RINGBUF map declaration""" + logger.info(f"Processing Ringbuf: {map_name}") + map_params = {"type": BPFMapType.RINGBUF} + + # Parse max_entries if present + if len(rval.args) >= 1 and isinstance(rval.args[0], ast.Constant): + const_val = rval.args[0].value + if isinstance(const_val, int): + map_params["max_entries"] = const_val + + for keyword in rval.keywords: + if keyword.arg == "max_entries" and isinstance(keyword.value, ast.Constant): + const_val = keyword.value.value + if isinstance(const_val, int): + map_params["max_entries"] = const_val + + logger.info(f"Ringbuf map parameters: {map_params}") + + map_global = create_bpf_map(module, map_name, map_params) + create_ringbuf_debug_info(module, map_global, map_name, map_params) + return map_global + + @MapProcessorRegistry.register("HashMap") def process_hash_map(map_name, rval, module): """Process a BPF_HASH map declaration""" diff --git a/tests/c-form/ringbuf.bpf.c b/tests/c-form/ringbuf.bpf.c index 648de2c..f0abb91 100644 --- a/tests/c-form/ringbuf.bpf.c +++ b/tests/c-form/ringbuf.bpf.c @@ -1,30 +1,51 @@ -#include "vmlinux.h" +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +#include #include #include -#include +#include +// Define the structure to be sent via ringbuf +struct event { + __u32 pid; + __u32 uid; + __u64 timestamp; + char comm[16]; // Process name +}; + +// Define the ringbuffer map struct { __uint(type, BPF_MAP_TYPE_RINGBUF); - __uint(max_entries, 1 << 24); // 16 MB -} rb SEC(".maps"); + __uint(max_entries, 256 * 1024); // 256 KB +} events SEC(".maps"); -//struct msg { -// u32 pid; -// char comm[16]; -//}; +// Tracepoint for execve system calls +SEC("tracepoint/syscalls/sys_enter_execve") +int trace_execve(void *ctx) +{ + struct event *e; + __u64 pid_tgid; + __u64 uid_gid; -//SEC("tracepoint/syscalls/sys_enter_execve") -//int handle_execve(struct trace_event_raw_sys_enter *ctx) -//{ -// struct msg *m; -// m = bpf_ringbuf_reserve(&rb, sizeof(*m), 0); -// if (!m) -// return 0; -// -// m->pid = bpf_get_current_pid_tgid() >> 32; -// bpf_get_current_comm(&m->comm, sizeof(m->comm)); -// bpf_ringbuf_submit(m, 0); -// return 0; -//} + // Reserve space in the ringbuffer + e = bpf_ringbuf_reserve(&events, sizeof(*e), 0); + if (!e) + return 0; -//char LICENSE[] SEC("license") = "GPL"; + // Fill the struct with data + pid_tgid = bpf_get_current_pid_tgid(); + e->pid = pid_tgid >> 32; + + uid_gid = bpf_get_current_uid_gid(); + e->uid = uid_gid & 0xFFFFFFFF; + + e->timestamp = bpf_ktime_get_ns(); + + bpf_get_current_comm(&e->comm, sizeof(e->comm)); + + // Submit the event to ringbuffer + bpf_ringbuf_submit(e, 0); + + return 0; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/tests/failing_tests/ringbuf.py b/tests/failing_tests/ringbuf.py index a6c60c8..0566d85 100644 --- a/tests/failing_tests/ringbuf.py +++ b/tests/failing_tests/ringbuf.py @@ -1,5 +1,5 @@ -from pythonbpf import bpf, map, bpfglobal, section -from pythonbpf.maps import RingBuf +from pythonbpf import bpf, BPF, map, bpfglobal, section, compile, compile_to_ir +from pythonbpf.maps import RingBuf, HashMap from ctypes import c_int32, c_void_p @@ -7,12 +7,19 @@ from ctypes import c_int32, c_void_p @bpf @map def mymap() -> RingBuf: - return RingBuf(max_entries=(1 << 24)) + return RingBuf(max_entries=(1024)) + + +@bpf +@map +def mymap2() -> HashMap: + return HashMap(key=c_int32, value=c_int32, max_entries=1024) @bpf @section("tracepoint/syscalls/sys_enter_clone") -def testing(ctx: c_void_p) -> c_int32: +def random_section(ctx: c_void_p) -> c_int32: + print("Hello") return c_int32(0) @@ -22,4 +29,7 @@ def LICENSE() -> str: return "GPL" +compile_to_ir("ringbuf.py", "ringbuf.ll") compile() +b = BPF() +b.load_and_attach()