|
| 1 | +""" |
| 2 | +Debug information generation module for Python-BPF |
| 3 | +Provides utilities for generating DWARF/BTF debug information |
| 4 | +""" |
| 5 | + |
| 6 | +from . import dwarf_constants as dc |
| 7 | +from typing import Dict, Any, List, Optional, Union |
| 8 | + |
| 9 | + |
| 10 | +class DebugInfoGenerator: |
| 11 | + def __init__(self, module): |
| 12 | + self.module = module |
| 13 | + self._type_cache = {} # Cache for common debug types |
| 14 | + |
| 15 | + def get_basic_type(self, name: str, size: int, encoding: int) -> Any: |
| 16 | + """Get or create a basic type with caching""" |
| 17 | + key = (name, size, encoding) |
| 18 | + if key not in self._type_cache: |
| 19 | + self._type_cache[key] = self.module.add_debug_info("DIBasicType", { |
| 20 | + "name": name, |
| 21 | + "size": size, |
| 22 | + "encoding": encoding |
| 23 | + }) |
| 24 | + return self._type_cache[key] |
| 25 | + |
| 26 | + def get_uint32_type(self) -> Any: |
| 27 | + """Get debug info for unsigned 32-bit integer""" |
| 28 | + return self.get_basic_type("unsigned int", 32, dc.DW_ATE_unsigned) |
| 29 | + |
| 30 | + def get_uint64_type(self) -> Any: |
| 31 | + """Get debug info for unsigned 64-bit integer""" |
| 32 | + return self.get_basic_type("unsigned long long", 64, dc.DW_ATE_unsigned) |
| 33 | + |
| 34 | + def create_pointer_type(self, base_type: Any, size: int = 64) -> Any: |
| 35 | + """Create a pointer type to the given base type""" |
| 36 | + return self.module.add_debug_info("DIDerivedType", { |
| 37 | + "tag": dc.DW_TAG_pointer_type, |
| 38 | + "baseType": base_type, |
| 39 | + "size": size |
| 40 | + }) |
| 41 | + |
| 42 | + def create_array_type(self, base_type: Any, count: int) -> Any: |
| 43 | + """Create an array type of the given base type with specified count""" |
| 44 | + subrange = self.module.add_debug_info("DISubrange", {"count": count}) |
| 45 | + return self.module.add_debug_info("DICompositeType", { |
| 46 | + "tag": dc.DW_TAG_array_type, |
| 47 | + "baseType": base_type, |
| 48 | + "size": self._compute_array_size(base_type, count), |
| 49 | + "elements": [subrange] |
| 50 | + }) |
| 51 | + |
| 52 | + @staticmethod |
| 53 | + def _compute_array_size(base_type: Any, count: int) -> int: |
| 54 | + # Extract size from base_type if possible |
| 55 | + # For simplicity, assuming base_type has a size attribute |
| 56 | + return getattr(base_type, "size", 32) * count |
| 57 | + |
| 58 | + def create_struct_member(self, name: str, base_type: Any, offset: int) -> Any: |
| 59 | + """Create a struct member with the given name, type, and offset""" |
| 60 | + return self.module.add_debug_info("DIDerivedType", { |
| 61 | + "tag": dc.DW_TAG_member, |
| 62 | + "name": name, |
| 63 | + "file": self.module._file_metadata, |
| 64 | + "baseType": base_type, |
| 65 | + "size": getattr(base_type, "size", 64), |
| 66 | + "offset": offset |
| 67 | + }) |
| 68 | + |
| 69 | + def create_struct_type(self, members: List[Any], size: int, is_distinct: bool) -> Any: |
| 70 | + """Create a struct type with the given members and size""" |
| 71 | + return self.module.add_debug_info("DICompositeType", { |
| 72 | + "tag": dc.DW_TAG_structure_type, |
| 73 | + "file": self.module._file_metadata, |
| 74 | + "size": size, |
| 75 | + "elements": members, |
| 76 | + }, is_distinct=is_distinct) |
| 77 | + |
| 78 | + def create_global_var_debug_info(self, name: str, var_type: Any, is_local: bool = False) -> Any: |
| 79 | + """Create debug info for a global variable""" |
| 80 | + global_var = self.module.add_debug_info("DIGlobalVariable", { |
| 81 | + "name": name, |
| 82 | + "scope": self.module._debug_compile_unit, |
| 83 | + "file": self.module._file_metadata, |
| 84 | + "type": var_type, |
| 85 | + "isLocal": is_local, |
| 86 | + "isDefinition": True |
| 87 | + }, is_distinct=True) |
| 88 | + |
| 89 | + return self.module.add_debug_info("DIGlobalVariableExpression", { |
| 90 | + "var": global_var, |
| 91 | + "expr": self.module.add_debug_info("DIExpression", {}) |
| 92 | + }) |
0 commit comments