@@ -16,10 +16,37 @@ def get_module_symbols(module_name: str):
1616 return [name for name in dir (imported_module )], imported_module
1717
1818
19+ def unwrap_pointer_type (type_obj : Any ) -> Any :
20+ """
21+ Recursively unwrap all pointer layers to get the base type.
22+
23+ This handles multiply nested pointers like LP_LP_struct_attribute_group
24+ and returns the base type (struct_attribute_group).
25+
26+ Stops unwrapping when reaching a non-pointer type (one without _type_ attribute).
27+
28+ Args:
29+ type_obj: The type object to unwrap
30+
31+ Returns:
32+ The base type after unwrapping all pointer layers
33+ """
34+ current_type = type_obj
35+ # Keep unwrapping while it's a pointer/array type (has _type_)
36+ # But stop if _type_ is just a string or basic type marker
37+ while hasattr (current_type , "_type_" ):
38+ next_type = current_type ._type_
39+ # Stop if _type_ is a string (like 'c' for c_char)
40+ if isinstance (next_type , str ):
41+ break
42+ current_type = next_type
43+ return current_type
44+
45+
1946def process_vmlinux_class (
20- node ,
21- llvm_module ,
22- handler : DependencyHandler ,
47+ node ,
48+ llvm_module ,
49+ handler : DependencyHandler ,
2350):
2451 symbols_in_module , imported_module = get_module_symbols ("vmlinux" )
2552 if node .name in symbols_in_module :
@@ -30,10 +57,10 @@ def process_vmlinux_class(
3057
3158
3259def process_vmlinux_post_ast (
33- elem_type_class ,
34- llvm_handler ,
35- handler : DependencyHandler ,
36- processing_stack = None ,
60+ elem_type_class ,
61+ llvm_handler ,
62+ handler : DependencyHandler ,
63+ processing_stack = None ,
3764):
3865 # Initialize processing stack on first call
3966 if processing_stack is None :
@@ -113,7 +140,7 @@ def process_vmlinux_post_ast(
113140
114141 # Process pointer to ctype
115142 if isinstance (elem_type , type ) and issubclass (
116- elem_type , ctypes ._Pointer
143+ elem_type , ctypes ._Pointer
117144 ):
118145 # Get the pointed-to type
119146 pointed_type = elem_type ._type_
@@ -126,7 +153,7 @@ def process_vmlinux_post_ast(
126153
127154 # Process function pointers (CFUNCTYPE)
128155 elif hasattr (elem_type , "_restype_" ) and hasattr (
129- elem_type , "_argtypes_"
156+ elem_type , "_argtypes_"
130157 ):
131158 # This is a CFUNCTYPE or similar
132159 logger .info (
@@ -158,13 +185,19 @@ def process_vmlinux_post_ast(
158185 if hasattr (elem_type , "_length_" ) and is_complex_type :
159186 type_length = elem_type ._length_
160187
161- if containing_type .__module__ == "vmlinux" :
162- new_dep_node .add_dependent (
163- elem_type ._type_ .__name__
164- if hasattr (elem_type ._type_ , "__name__" )
165- else str (elem_type ._type_ )
188+ # Unwrap all pointer layers to get the base type for dependency tracking
189+ base_type = unwrap_pointer_type (elem_type )
190+ base_type_module = getattr (base_type , "__module__" , None )
191+
192+ if base_type_module == "vmlinux" :
193+ base_type_name = (
194+ base_type .__name__
195+ if hasattr (base_type , "__name__" )
196+ else str (base_type )
166197 )
167- elif containing_type .__module__ == ctypes .__name__ :
198+ new_dep_node .add_dependent (base_type_name )
199+ elif base_type_module == ctypes .__name__ or base_type_module is None :
200+ # Handle ctypes or types with no module (like some internal ctypes types)
168201 if isinstance (elem_type , type ):
169202 if issubclass (elem_type , ctypes .Array ):
170203 ctype_complex_type = ctypes .Array
@@ -178,7 +211,7 @@ def process_vmlinux_post_ast(
178211 raise TypeError ("Unsupported ctypes subclass" )
179212 else :
180213 raise ImportError (
181- f"Unsupported module of { containing_type } "
214+ f"Unsupported module of { base_type } : { base_type_module } "
182215 )
183216 logger .debug (
184217 f"{ containing_type } containing type of parent { elem_name } with { elem_type } and ctype { ctype_complex_type } and length { type_length } "
@@ -191,11 +224,16 @@ def process_vmlinux_post_ast(
191224 elem_name , ctype_complex_type
192225 )
193226 new_dep_node .set_field_type (elem_name , elem_type )
194- if containing_type .__module__ == "vmlinux" :
227+
228+ # Check the containing_type module to decide whether to recurse
229+ containing_type_module = getattr (containing_type , "__module__" , None )
230+ if containing_type_module == "vmlinux" :
231+ # Also unwrap containing_type to get base type name
232+ base_containing_type = unwrap_pointer_type (containing_type )
195233 containing_type_name = (
196- containing_type .__name__
197- if hasattr (containing_type , "__name__" )
198- else str (containing_type )
234+ base_containing_type .__name__
235+ if hasattr (base_containing_type , "__name__" )
236+ else str (base_containing_type )
199237 )
200238
201239 # Check for self-reference or already processed
@@ -212,21 +250,21 @@ def process_vmlinux_post_ast(
212250 )
213251 new_dep_node .set_field_ready (elem_name , True )
214252 else :
215- # Process recursively - THIS WAS MISSING
253+ # Process recursively - use base containing type, not the pointer wrapper
216254 new_dep_node .add_dependent (containing_type_name )
217255 process_vmlinux_post_ast (
218- containing_type ,
256+ base_containing_type ,
219257 llvm_handler ,
220258 handler ,
221259 processing_stack ,
222260 )
223261 new_dep_node .set_field_ready (elem_name , True )
224- elif containing_type . __module__ == ctypes .__name__ :
262+ elif containing_type_module == ctypes .__name__ or containing_type_module is None :
225263 logger .debug (f"Processing ctype internal{ containing_type } " )
226264 new_dep_node .set_field_ready (elem_name , True )
227265 else :
228266 raise TypeError (
229- "Module not supported in recursive resolution"
267+ f "Module not supported in recursive resolution: { containing_type_module } "
230268 )
231269 else :
232270 new_dep_node .add_dependent (
@@ -245,9 +283,12 @@ def process_vmlinux_post_ast(
245283 raise ValueError (
246284 f"{ elem_name } with type { elem_type } from module { module_name } not supported in recursive resolver"
247285 )
248-
286+ elif module_name == ctypes .__name__ or module_name is None :
287+ # Handle ctypes types - these don't need processing, just return
288+ logger .debug (f"Skipping ctypes type { current_symbol_name } " )
289+ return True
249290 else :
250- raise ImportError ("UNSUPPORTED Module" )
291+ raise ImportError (f "UNSUPPORTED Module { module_name } " )
251292
252293 logger .info (
253294 f"{ current_symbol_name } processed and handler readiness { handler .is_ready } "
0 commit comments