11import ast
2+ import logging
23from logging import Logger
34from llvmlite import ir
4- from enum import Enum
5+
56from .maps_utils import MapProcessorRegistry
6- from pythonbpf . debuginfo import DebugInfoGenerator
7- import logging
7+ from . map_types import BPFMapType
8+ from . map_debug_info import create_map_debug_info , create_ringbuf_debug_info
89
910logger : Logger = logging .getLogger (__name__ )
1011
@@ -26,44 +27,6 @@ def is_map(func_node):
2627 )
2728
2829
29- class BPFMapType (Enum ):
30- UNSPEC = 0
31- HASH = 1
32- ARRAY = 2
33- PROG_ARRAY = 3
34- PERF_EVENT_ARRAY = 4
35- PERCPU_HASH = 5
36- PERCPU_ARRAY = 6
37- STACK_TRACE = 7
38- CGROUP_ARRAY = 8
39- LRU_HASH = 9
40- LRU_PERCPU_HASH = 10
41- LPM_TRIE = 11
42- ARRAY_OF_MAPS = 12
43- HASH_OF_MAPS = 13
44- DEVMAP = 14
45- SOCKMAP = 15
46- CPUMAP = 16
47- XSKMAP = 17
48- SOCKHASH = 18
49- CGROUP_STORAGE_DEPRECATED = 19
50- CGROUP_STORAGE = 19
51- REUSEPORT_SOCKARRAY = 20
52- PERCPU_CGROUP_STORAGE_DEPRECATED = 21
53- PERCPU_CGROUP_STORAGE = 21
54- QUEUE = 22
55- STACK = 23
56- SK_STORAGE = 24
57- DEVMAP_HASH = 25
58- STRUCT_OPS = 26
59- RINGBUF = 27
60- INODE_STORAGE = 28
61- TASK_STORAGE = 29
62- BLOOM_FILTER = 30
63- USER_RINGBUF = 31
64- CGRP_STORAGE = 32
65-
66-
6730def create_bpf_map (module , map_name , map_params ):
6831 """Create a BPF map in the module with given parameters and debug info"""
6932
@@ -84,114 +47,37 @@ def create_bpf_map(module, map_name, map_params):
8447 return map_global
8548
8649
87- def create_map_debug_info (module , map_global , map_name , map_params ):
88- """Generate debug info metadata for BPF maps HASH and PERF_EVENT_ARRAY"""
89- generator = DebugInfoGenerator (module )
90-
91- uint_type = generator .get_uint32_type ()
92- ulong_type = generator .get_uint64_type ()
93- array_type = generator .create_array_type (
94- uint_type , map_params .get ("type" , BPFMapType .UNSPEC ).value
95- )
96- type_ptr = generator .create_pointer_type (array_type , 64 )
97- key_ptr = generator .create_pointer_type (
98- array_type if "key_size" in map_params else ulong_type , 64
99- )
100- value_ptr = generator .create_pointer_type (
101- array_type if "value_size" in map_params else ulong_type , 64
102- )
103-
104- elements_arr = []
105-
106- # Create struct members
107- # scope field does not appear for some reason
108- cnt = 0
109- for elem in map_params :
110- if elem == "max_entries" :
111- continue
112- if elem == "type" :
113- ptr = type_ptr
114- elif "key" in elem :
115- ptr = key_ptr
116- else :
117- ptr = value_ptr
118- # TODO: the best way to do this is not 64, but get the size each time. this will not work for structs.
119- member = generator .create_struct_member (elem , ptr , cnt * 64 )
120- elements_arr .append (member )
121- cnt += 1
122-
123- if "max_entries" in map_params :
124- max_entries_array = generator .create_array_type (
125- uint_type , map_params ["max_entries" ]
126- )
127- max_entries_ptr = generator .create_pointer_type (max_entries_array , 64 )
128- max_entries_member = generator .create_struct_member (
129- "max_entries" , max_entries_ptr , cnt * 64
130- )
131- elements_arr .append (max_entries_member )
132-
133- # Create the struct type
134- struct_type = generator .create_struct_type (
135- elements_arr , 64 * len (elements_arr ), is_distinct = True
136- )
137-
138- # Create global variable debug info
139- global_var = generator .create_global_var_debug_info (
140- map_name , struct_type , is_local = False
141- )
142-
143- # Attach debug info to the global variable
144- map_global .set_metadata ("dbg" , global_var )
145-
146- return global_var
50+ def _parse_map_params (rval , expected_args = None ):
51+ """Parse map parameters from call arguments and keywords."""
14752
53+ params = {}
14854
149- def create_ringbuf_debug_info (module , map_global , map_name , map_params ):
150- """Generate debug information metadata for BPF RINGBUF map"""
151- generator = DebugInfoGenerator (module )
55+ # Parse positional arguments
56+ if expected_args :
57+ for i , arg_name in enumerate (expected_args ):
58+ if i < len (rval .args ):
59+ arg = rval .args [i ]
60+ if isinstance (arg , ast .Name ):
61+ params [arg_name ] = arg .id
62+ elif isinstance (arg , ast .Constant ):
63+ params [arg_name ] = arg .value
15264
153- int_type = generator .get_int32_type ()
154-
155- type_array = generator .create_array_type (
156- int_type , map_params .get ("type" , BPFMapType .RINGBUF ).value
157- )
158- type_ptr = generator .create_pointer_type (type_array , 64 )
159- type_member = generator .create_struct_member ("type" , type_ptr , 0 )
160-
161- max_entries_array = generator .create_array_type (int_type , map_params ["max_entries" ])
162- max_entries_ptr = generator .create_pointer_type (max_entries_array , 64 )
163- max_entries_member = generator .create_struct_member (
164- "max_entries" , max_entries_ptr , 64
165- )
166-
167- elements_arr = [type_member , max_entries_member ]
168-
169- struct_type = generator .create_struct_type (elements_arr , 128 , is_distinct = True )
65+ # Parse keyword arguments (override positional)
66+ for keyword in rval .keywords :
67+ if isinstance (keyword .value , ast .Name ):
68+ params [keyword .arg ] = keyword .value .id
69+ elif isinstance (keyword .value , ast .Constant ):
70+ params [keyword .arg ] = keyword .value .value
17071
171- global_var = generator .create_global_var_debug_info (
172- map_name , struct_type , is_local = False
173- )
174- map_global .set_metadata ("dbg" , global_var )
175- return global_var
72+ return params
17673
17774
17875@MapProcessorRegistry .register ("RingBuf" )
17976def process_ringbuf_map (map_name , rval , module ):
18077 """Process a BPF_RINGBUF map declaration"""
18178 logger .info (f"Processing Ringbuf: { map_name } " )
182- map_params = {"type" : BPFMapType .RINGBUF }
183-
184- # Parse max_entries if present
185- if len (rval .args ) >= 1 and isinstance (rval .args [0 ], ast .Constant ):
186- const_val = rval .args [0 ].value
187- if isinstance (const_val , int ):
188- map_params ["max_entries" ] = const_val
189-
190- for keyword in rval .keywords :
191- if keyword .arg == "max_entries" and isinstance (keyword .value , ast .Constant ):
192- const_val = keyword .value .value
193- if isinstance (const_val , int ):
194- map_params ["max_entries" ] = const_val
79+ map_params = _parse_map_params (rval , expected_args = ["max_entries" ])
80+ map_params ["type" ] = BPFMapType .RINGBUF
19581
19682 logger .info (f"Ringbuf map parameters: { map_params } " )
19783
@@ -204,27 +90,8 @@ def process_ringbuf_map(map_name, rval, module):
20490def process_hash_map (map_name , rval , module ):
20591 """Process a BPF_HASH map declaration"""
20692 logger .info (f"Processing HashMap: { map_name } " )
207- map_params = {"type" : BPFMapType .HASH }
208-
209- # Assuming order: key_type, value_type, max_entries
210- if len (rval .args ) >= 1 and isinstance (rval .args [0 ], ast .Name ):
211- map_params ["key" ] = rval .args [0 ].id
212- if len (rval .args ) >= 2 and isinstance (rval .args [1 ], ast .Name ):
213- map_params ["value" ] = rval .args [1 ].id
214- if len (rval .args ) >= 3 and isinstance (rval .args [2 ], ast .Constant ):
215- const_val = rval .args [2 ].value
216- if isinstance (const_val , (int , str )): # safe check
217- map_params ["max_entries" ] = const_val
218-
219- for keyword in rval .keywords :
220- if keyword .arg == "key" and isinstance (keyword .value , ast .Name ):
221- map_params ["key" ] = keyword .value .id
222- elif keyword .arg == "value" and isinstance (keyword .value , ast .Name ):
223- map_params ["value" ] = keyword .value .id
224- elif keyword .arg == "max_entries" and isinstance (keyword .value , ast .Constant ):
225- const_val = keyword .value .value
226- if isinstance (const_val , (int , str )):
227- map_params ["max_entries" ] = const_val
93+ map_params = _parse_map_params (rval , expected_args = ["key" , "value" , "max_entries" ])
94+ map_params ["type" ] = BPFMapType .HASH
22895
22996 logger .info (f"Map parameters: { map_params } " )
23097 map_global = create_bpf_map (module , map_name , map_params )
@@ -237,18 +104,8 @@ def process_hash_map(map_name, rval, module):
237104def process_perf_event_map (map_name , rval , module ):
238105 """Process a BPF_PERF_EVENT_ARRAY map declaration"""
239106 logger .info (f"Processing PerfEventArray: { map_name } " )
240- map_params = {"type" : BPFMapType .PERF_EVENT_ARRAY }
241-
242- if len (rval .args ) >= 1 and isinstance (rval .args [0 ], ast .Name ):
243- map_params ["key_size" ] = rval .args [0 ].id
244- if len (rval .args ) >= 2 and isinstance (rval .args [1 ], ast .Name ):
245- map_params ["value_size" ] = rval .args [1 ].id
246-
247- for keyword in rval .keywords :
248- if keyword .arg == "key_size" and isinstance (keyword .value , ast .Name ):
249- map_params ["key_size" ] = keyword .value .id
250- elif keyword .arg == "value_size" and isinstance (keyword .value , ast .Name ):
251- map_params ["value_size" ] = keyword .value .id
107+ map_params = _parse_map_params (rval , expected_args = ["key_size" , "value_size" ])
108+ map_params ["type" ] = BPFMapType .PERF_EVENT_ARRAY
252109
253110 logger .info (f"Map parameters: { map_params } " )
254111 map_global = create_bpf_map (module , map_name , map_params )
0 commit comments