From e80486975f1043530e68d7642823992ed0db3040 Mon Sep 17 00:00:00 2001 From: varun-r-mallya Date: Tue, 30 Sep 2025 20:31:00 +0530 Subject: [PATCH] Add DebugInfoGenerator class --- pythonbpf/debuginfo/__init__.py | 1 + pythonbpf/debuginfo/debug_info_generator.py | 92 +++++++++++++++++++++ pythonbpf/maps/maps_pass.py | 2 +- 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 pythonbpf/debuginfo/debug_info_generator.py diff --git a/pythonbpf/debuginfo/__init__.py b/pythonbpf/debuginfo/__init__.py index 4647663..faeabe4 100644 --- a/pythonbpf/debuginfo/__init__.py +++ b/pythonbpf/debuginfo/__init__.py @@ -1,2 +1,3 @@ from .dwarf_constants import * from .dtypes import * +from .debug_info_generator import DebugInfoGenerator diff --git a/pythonbpf/debuginfo/debug_info_generator.py b/pythonbpf/debuginfo/debug_info_generator.py new file mode 100644 index 0000000..f4972c8 --- /dev/null +++ b/pythonbpf/debuginfo/debug_info_generator.py @@ -0,0 +1,92 @@ +""" +Debug information generation module for Python-BPF +Provides utilities for generating DWARF/BTF debug information +""" + +from . import dwarf_constants as dc +from typing import Dict, Any, List, Optional, Union + + +class DebugInfoGenerator: + def __init__(self, module): + self.module = module + self._type_cache = {} # Cache for common debug types + + def get_basic_type(self, name: str, size: int, encoding: int) -> Any: + """Get or create a basic type with caching""" + key = (name, size, encoding) + if key not in self._type_cache: + self._type_cache[key] = self.module.add_debug_info("DIBasicType", { + "name": name, + "size": size, + "encoding": encoding + }) + return self._type_cache[key] + + def get_uint32_type(self) -> Any: + """Get debug info for unsigned 32-bit integer""" + return self.get_basic_type("unsigned int", 32, dc.DW_ATE_unsigned) + + def get_uint64_type(self) -> Any: + """Get debug info for unsigned 64-bit integer""" + return self.get_basic_type("unsigned long long", 64, dc.DW_ATE_unsigned) + + def create_pointer_type(self, base_type: Any, size: int = 64) -> Any: + """Create a pointer type to the given base type""" + return self.module.add_debug_info("DIDerivedType", { + "tag": dc.DW_TAG_pointer_type, + "baseType": base_type, + "size": size + }) + + def create_array_type(self, base_type: Any, count: int) -> Any: + """Create an array type of the given base type with specified count""" + subrange = self.module.add_debug_info("DISubrange", {"count": count}) + return self.module.add_debug_info("DICompositeType", { + "tag": dc.DW_TAG_array_type, + "baseType": base_type, + "size": self._compute_array_size(base_type, count), + "elements": [subrange] + }) + + @staticmethod + def _compute_array_size(base_type: Any, count: int) -> int: + # Extract size from base_type if possible + # For simplicity, assuming base_type has a size attribute + return getattr(base_type, "size", 32) * count + + def create_struct_member(self, name: str, base_type: Any, offset: int) -> Any: + """Create a struct member with the given name, type, and offset""" + return self.module.add_debug_info("DIDerivedType", { + "tag": dc.DW_TAG_member, + "name": name, + "file": self.module._file_metadata, + "baseType": base_type, + "size": getattr(base_type, "size", 64), + "offset": offset + }) + + def create_struct_type(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("DICompositeType", { + "tag": dc.DW_TAG_structure_type, + "file": self.module._file_metadata, + "size": size, + "elements": members, + }, is_distinct=is_distinct) + + def create_global_var_debug_info(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("DIGlobalVariable", { + "name": name, + "scope": self.module._debug_compile_unit, + "file": self.module._file_metadata, + "type": var_type, + "isLocal": is_local, + "isDefinition": True + }, is_distinct=True) + + return self.module.add_debug_info("DIGlobalVariableExpression", { + "var": global_var, + "expr": self.module.add_debug_info("DIExpression", {}) + }) diff --git a/pythonbpf/maps/maps_pass.py b/pythonbpf/maps/maps_pass.py index 652d819..abb7734 100644 --- a/pythonbpf/maps/maps_pass.py +++ b/pythonbpf/maps/maps_pass.py @@ -2,7 +2,7 @@ import ast from llvmlite import ir from enum import Enum from .maps_utils import MapProcessorRegistry -from ..debuginfo import dwarf_constants as dc +from ..debuginfo import dwarf_constants as dc, DebugInfoGenerator import logging logger = logging.getLogger(__name__)