From f263c351563f616a694b1ef8aa285d8aa4411c81 Mon Sep 17 00:00:00 2001 From: varun-r-mallya Date: Thu, 2 Oct 2025 19:05:58 +0530 Subject: [PATCH] move debug cu generation to debug module --- pythonbpf/codegen.py | 40 ++++++--------------- pythonbpf/debuginfo/debug_info_generator.py | 30 ++++++++++++++-- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/pythonbpf/codegen.py b/pythonbpf/codegen.py index 9284073..36f7a37 100644 --- a/pythonbpf/codegen.py +++ b/pythonbpf/codegen.py @@ -5,7 +5,7 @@ from .functions_pass import func_proc from .maps import maps_proc from .structs import structs_proc from .globals_pass import globals_processing -from .debuginfo import DW_LANG_C11, DwarfBehaviorEnum +from .debuginfo import DW_LANG_C11, DwarfBehaviorEnum, DebugInfoGenerator import os import subprocess import inspect @@ -60,32 +60,14 @@ def compile_to_ir(filename: str, output: str, loglevel=logging.WARNING): module.triple = "bpf" if not hasattr(module, "_debug_compile_unit"): - module._file_metadata = module.add_debug_info( - "DIFile", - { # type: ignore - "filename": filename, - "directory": os.path.dirname(filename), - }, - ) - - module._debug_compile_unit = module.add_debug_info( - "DICompileUnit", - { # type: ignore - "language": DW_LANG_C11, - "file": module._file_metadata, # type: ignore - "producer": f"PythonBPF {VERSION}", - "isOptimized": True, # TODO: This is probably not true - # TODO: add a global field here that keeps track of all the globals. Works without it, but I think it might - # be required for kprobes. - "runtimeVersion": 0, - "emissionKind": 1, - "splitDebugInlining": False, - "nameTableKind": 0, - }, - is_distinct=True, - ) - - module.add_named_metadata("llvm.dbg.cu", module._debug_compile_unit) # type: ignore + debug_generator = DebugInfoGenerator(module) + debug_generator.generate_file_metadata(filename, os.path.dirname(filename)) + debug_generator.generate_debug_cu(DW_LANG_C11, + f"PythonBPF {VERSION}", + True # TODO: This is probably not true + # TODO: add a global field here that keeps track of all the globals. Works without it, but I think it might + # be required for kprobes. + , True) processor(source, filename, module) @@ -147,7 +129,7 @@ def compile(loglevel=logging.WARNING) -> bool: success = True success = ( - compile_to_ir(str(caller_file), str(ll_file), loglevel=loglevel) and success + compile_to_ir(str(caller_file), str(ll_file), loglevel=loglevel) and success ) success = bool( @@ -174,7 +156,7 @@ def BPF(loglevel=logging.WARNING) -> BpfProgram: caller_frame = inspect.stack()[1] src = inspect.getsource(caller_frame.frame) with tempfile.NamedTemporaryFile( - mode="w+", delete=True, suffix=".py" + mode="w+", delete=True, suffix=".py" ) as f, tempfile.NamedTemporaryFile( mode="w+", delete=True, suffix=".ll" ) as inter, tempfile.NamedTemporaryFile( diff --git a/pythonbpf/debuginfo/debug_info_generator.py b/pythonbpf/debuginfo/debug_info_generator.py index da0e86a..6de705b 100644 --- a/pythonbpf/debuginfo/debug_info_generator.py +++ b/pythonbpf/debuginfo/debug_info_generator.py @@ -12,6 +12,32 @@ class DebugInfoGenerator: self.module = module self._type_cache = {} # Cache for common debug types + def generate_file_metadata(self, filename, dirname): + self.module._file_metadata = self.module.add_debug_info( + "DIFile", + { # type: ignore + "filename": filename, + "directory": dirname, + }, + ) + + def generate_debug_cu(self, language, producer: str, is_optimized: bool, is_distinct: bool): + self.module._debug_compile_unit = self.module.add_debug_info( + "DICompileUnit", + { # type: ignore + "language": language, + "file": self.module._file_metadata, # type: ignore + "producer": producer, + "isOptimized": is_optimized, + "runtimeVersion": 0, + "emissionKind": 1, + "splitDebugInlining": False, + "nameTableKind": 0, + }, + is_distinct=is_distinct, + ) + self.module.add_named_metadata("llvm.dbg.cu", self.module._debug_compile_unit) # type: ignore + def get_basic_type(self, name: str, size: int, encoding: int) -> Any: """Get or create a basic type with caching""" key = (name, size, encoding) @@ -74,7 +100,7 @@ class DebugInfoGenerator: ) def create_struct_type( - self, members: List[Any], size: int, is_distinct: bool + self, members: List[Any], size: int, is_distinct: bool ) -> Any: """Create a struct type with the given members and size""" return self.module.add_debug_info( @@ -89,7 +115,7 @@ class DebugInfoGenerator: ) def create_global_var_debug_info( - self, name: str, var_type: Any, is_local: bool = False + self, name: str, var_type: Any, is_local: bool = False ) -> Any: """Create debug info for a global variable""" global_var = self.module.add_debug_info(