mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2025-12-31 21:06:25 +00:00
members generated for simple ctypes
This commit is contained in:
@ -1,20 +1,155 @@
|
||||
from pythonbpf.debuginfo import DebugInfoGenerator
|
||||
from pythonbpf.debuginfo import DebugInfoGenerator, dwarf_constants as dc
|
||||
from ..dependency_node import DependencyNode
|
||||
import ctypes
|
||||
import logging
|
||||
from typing import List, Any, Tuple, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def debug_info_generation(
|
||||
struct: DependencyNode, llvm_module, generated_debug_info: list
|
||||
):
|
||||
struct: DependencyNode, llvm_module, generated_debug_info: List[Tuple[DependencyNode, Any]]
|
||||
) -> Any:
|
||||
"""
|
||||
Generate DWARF debug information for a struct defined in a DependencyNode.
|
||||
|
||||
Args:
|
||||
struct: The dependency node containing struct information
|
||||
llvm_module: The LLVM module to add debug info to
|
||||
generated_debug_info: List of tuples (struct, debug_info) to track generated debug info
|
||||
|
||||
Returns:
|
||||
The generated global variable debug info
|
||||
"""
|
||||
# Set up debug info generator
|
||||
generator = DebugInfoGenerator(llvm_module)
|
||||
|
||||
# Check if debug info for this struct has already been generated
|
||||
for existing_struct, debug_info in generated_debug_info:
|
||||
if existing_struct.name == struct.name:
|
||||
return debug_info
|
||||
|
||||
# Process all fields and create members for the struct
|
||||
members = []
|
||||
uint32type = generator.get_uint32_type()
|
||||
for field_name, field in struct.fields.items():
|
||||
members.append(generator.create_struct_member(field_name, uint32type, field.offset))
|
||||
# Get appropriate debug type for this field
|
||||
field_type = _get_field_debug_type(
|
||||
field_name, field, generator, struct, generated_debug_info
|
||||
)
|
||||
# Create struct member with proper offset
|
||||
member = generator.create_struct_member_vmlinux(
|
||||
field_name, field_type, field.offset * 8
|
||||
)
|
||||
members.append(member)
|
||||
|
||||
struct_type = generator.create_struct_type(members, struct.__sizeof__(), is_distinct=True)
|
||||
|
||||
global_var = generator.create_global_var_debug_info(
|
||||
struct.name, struct_type, is_local=False
|
||||
if struct.name.startswith("struct_"):
|
||||
struct_name = struct.name.removeprefix("struct_")
|
||||
else:
|
||||
raise ValueError("Unions are not supported in the current version")
|
||||
# Create struct type with all members
|
||||
struct_type = generator.create_struct_type_with_name(
|
||||
struct_name, members, struct.__sizeof__() * 8, is_distinct=True
|
||||
)
|
||||
|
||||
return global_var
|
||||
return struct_type
|
||||
|
||||
|
||||
def _get_field_debug_type(
|
||||
field_name: str,
|
||||
field,
|
||||
generator: DebugInfoGenerator,
|
||||
parent_struct: DependencyNode,
|
||||
generated_debug_info: List[Tuple[DependencyNode, Any]]
|
||||
) -> Any:
|
||||
"""
|
||||
Determine the appropriate debug type for a field based on its Python/ctypes type.
|
||||
|
||||
Args:
|
||||
field_name: Name of the field
|
||||
field: Field object containing type information
|
||||
generator: DebugInfoGenerator instance
|
||||
parent_struct: The parent struct containing this field
|
||||
generated_debug_info: List of already generated debug info
|
||||
|
||||
Returns:
|
||||
The debug info type for this field
|
||||
"""
|
||||
# Handle complex types (arrays, pointers)
|
||||
if field.ctype_complex_type is not None:
|
||||
if issubclass(field.ctype_complex_type, ctypes.Array):
|
||||
# Handle array types
|
||||
element_type = _get_basic_debug_type(field.containing_type, generator)
|
||||
return generator.create_array_type(element_type, field.type_size)
|
||||
elif issubclass(field.ctype_complex_type, ctypes._Pointer):
|
||||
# Handle pointer types
|
||||
pointee_type = _get_basic_debug_type(field.containing_type, generator)
|
||||
return generator.create_pointer_type(pointee_type)
|
||||
|
||||
# Handle other vmlinux types (nested structs)
|
||||
if field.type.__module__ == "vmlinux":
|
||||
# If it's a struct from vmlinux, check if we've already generated debug info for it
|
||||
struct_name = field.type.__name__
|
||||
|
||||
# Look for existing debug info in the list
|
||||
for existing_struct, debug_info in generated_debug_info:
|
||||
if existing_struct.name == struct_name:
|
||||
# Use existing debug info
|
||||
return debug_info
|
||||
|
||||
# If not found, create a forward declaration
|
||||
# This will be completed when the actual struct is processed
|
||||
logger.warning("Forward declaration in struct created")
|
||||
forward_type = generator.create_struct_type([], 0, is_distinct=True)
|
||||
return forward_type
|
||||
|
||||
# Handle basic C types
|
||||
return _get_basic_debug_type(field.type, generator)
|
||||
|
||||
|
||||
def _get_basic_debug_type(ctype, generator: DebugInfoGenerator) -> Any:
|
||||
"""
|
||||
Map a ctypes type to a DWARF debug type.
|
||||
|
||||
Args:
|
||||
ctype: A ctypes type or Python type
|
||||
generator: DebugInfoGenerator instance
|
||||
|
||||
Returns:
|
||||
The corresponding debug type
|
||||
"""
|
||||
# Map ctypes to debug info types
|
||||
if ctype == ctypes.c_char or ctype == ctypes.c_byte:
|
||||
return generator.get_basic_type("char", 8, dc.DW_ATE_signed_char), 8
|
||||
elif ctype == ctypes.c_ubyte or ctype == ctypes.c_uint8:
|
||||
return generator.get_basic_type("unsigned char", 8, dc.DW_ATE_unsigned_char), 8
|
||||
elif ctype == ctypes.c_short or ctype == ctypes.c_int16:
|
||||
return generator.get_basic_type("short", 16, dc.DW_ATE_signed), 16
|
||||
elif ctype == ctypes.c_ushort or ctype == ctypes.c_uint16:
|
||||
return generator.get_basic_type("unsigned short", 16, dc.DW_ATE_unsigned), 16
|
||||
elif ctype == ctypes.c_int or ctype == ctypes.c_int32:
|
||||
return generator.get_basic_type("int", 32, dc.DW_ATE_signed), 32
|
||||
elif ctype == ctypes.c_uint or ctype == ctypes.c_uint32:
|
||||
return generator.get_basic_type("unsigned int", 32, dc.DW_ATE_unsigned), 32
|
||||
elif ctype == ctypes.c_long:
|
||||
return generator.get_basic_type("long", 64, dc.DW_ATE_signed), 64
|
||||
elif ctype == ctypes.c_ulong:
|
||||
return generator.get_basic_type("unsigned long", 64, dc.DW_ATE_unsigned), 64
|
||||
elif ctype == ctypes.c_longlong or ctype == ctypes.c_int64:
|
||||
return generator.get_basic_type("long long", 64, dc.DW_ATE_signed), 64
|
||||
elif ctype == ctypes.c_ulonglong or ctype == ctypes.c_uint64:
|
||||
return generator.get_basic_type("unsigned long long", 64, dc.DW_ATE_unsigned), 64
|
||||
elif ctype == ctypes.c_float:
|
||||
return generator.get_basic_type("float", 32, dc.DW_ATE_float), 32
|
||||
elif ctype == ctypes.c_double:
|
||||
return generator.get_basic_type("double", 64, dc.DW_ATE_float), 64
|
||||
elif ctype == ctypes.c_bool:
|
||||
return generator.get_basic_type("bool", 8, dc.DW_ATE_boolean), 8
|
||||
elif ctype == ctypes.c_char_p:
|
||||
char_type = generator.get_basic_type("char", 8, dc.DW_ATE_signed_char), 8
|
||||
return generator.create_pointer_type(char_type)
|
||||
elif ctype == ctypes.c_void_p:
|
||||
void_type = generator.module.add_debug_info(
|
||||
"DIBasicType", {"name": "void"}
|
||||
)
|
||||
return generator.create_pointer_type(void_type), 64
|
||||
else:
|
||||
return generator.get_uint64_type(), 64
|
||||
|
||||
Reference in New Issue
Block a user