diff --git a/examples/execve.py b/examples/execve.py index fc1598f..1fc215a 100644 --- a/examples/execve.py +++ b/examples/execve.py @@ -1,8 +1,9 @@ from pythonbpf.decorators import tracepoint +from ctypes import c_void_p, c_int32 @tracepoint("syscalls:sys_enter_execve") -def trace_execve(ctx) -> int: +def trace_execve(ctx: c_void_p) -> c_int32: print("execve called\n") - return 0 + return c_int32(0) LICENSE = "GPL" diff --git a/pythonbpf/codegen.py b/pythonbpf/codegen.py index 335eb10..74b6031 100644 --- a/pythonbpf/codegen.py +++ b/pythonbpf/codegen.py @@ -1,10 +1,16 @@ import ast from llvmlite import ir from .license_pass import license_processing +from .functions_pass import functions_processing def processor(source_code, filename, module): tree = ast.parse(source_code, filename) - license_processing(tree, module) + print(ast.dump(tree)) + section_names = [] + section_names.append(license_processing(tree, module)) + section_names.append(functions_processing(tree, module)) + if any(name is None for name in section_names): + print("Processing failed") def compile_to_ir(filename: str, output: str): with open(filename) as f: diff --git a/pythonbpf/functions_pass.py b/pythonbpf/functions_pass.py new file mode 100644 index 0000000..ee58229 --- /dev/null +++ b/pythonbpf/functions_pass.py @@ -0,0 +1,32 @@ +from llvmlite import ir +import ast + +def emit_function(module: ir.Module, license_str: str): + license_bytes = license_str.encode("utf8") + b"\x00" + elems = [ir.Constant(ir.IntType(8), b) for b in license_bytes] + ty = ir.ArrayType(ir.IntType(8), len(elems)) + + gvar = ir.GlobalVariable(module, ty, name="LICENSE") + + gvar.initializer = ir.Constant(ty, elems) # type: ignore + + gvar.align = 1 # type: ignore + gvar.linkage = "dso_local" # type: ignore + gvar.global_constant = False + gvar.section = "license" # type: ignore + + return gvar + +def functions_processing(tree, module): + bpf_functions = [] + helper_functions = [] + for node in tree.body: + section_name = "" + if isinstance(node, ast.FunctionDef): + if len(node.decorator_list) == 1: + bpf_functions.append(node) + else: + if 'helper_functions' not in locals(): + helper_functions.append(node) + + diff --git a/pythonbpf/license_pass.py b/pythonbpf/license_pass.py index 7013077..0f986a0 100644 --- a/pythonbpf/license_pass.py +++ b/pythonbpf/license_pass.py @@ -12,12 +12,13 @@ def emit_license(module: ir.Module, license_str: str): gvar.align = 1 # type: ignore gvar.linkage = "dso_local" # type: ignore - gvar.global_constant = False # must be global, not constant + gvar.global_constant = False gvar.section = "license" # type: ignore return gvar def license_processing(tree, module): + """Process the LICENSE assignment in the given AST tree and return the section name""" count = 0 for node in tree.body: if isinstance(node, ast.Assign): @@ -27,7 +28,10 @@ def license_processing(tree, module): count += 1 if isinstance(node.value, ast.Constant) and isinstance(node.value.value, str): emit_license(module, node.value.value) + return "LICENSE" else: print("ERROR: LICENSE must be a string literal") + return None else: print("ERROR: LICENSE already assigned") + return None diff --git a/pythonbpf/type_deducer.py b/pythonbpf/type_deducer.py new file mode 100644 index 0000000..2f58a1d --- /dev/null +++ b/pythonbpf/type_deducer.py @@ -0,0 +1,29 @@ +import ctypes +from llvmlite import ir + +def ctypes_to_ir(ctype): + if ctype is ctypes.c_int32: + return ir.IntType(32) + if ctype is ctypes.c_int64: + return ir.IntType(64) + if ctype is ctypes.c_uint8: + return ir.IntType(8) + if ctype is ctypes.c_double: + return ir.DoubleType() + if ctype is ctypes.c_float: + return ir.FloatType() + + # pointers + if hasattr(ctype, "_type_") and hasattr(ctype, "_length_"): + # ctypes array + return ir.ArrayType(ctypes_to_ir(ctype._type_), ctype._length_) + + # if hasattr(ctype, "_type_") and issubclass(ctype, ctypes._Pointer): + # return ir.PointerType(ctypes_to_ir(ctype._type_)) + + # structs + if issubclass(ctype, ctypes.Structure): + fields = [ctypes_to_ir(f[1]) for f in ctype._fields_] + return ir.LiteralStructType(fields) + + raise NotImplementedError(f"No mapping for {ctype}")