44from .bpf_helper_handler import bpf_printk_emitter , bpf_ktime_get_ns_emitter
55from .type_deducer import ctypes_to_ir
66
7+
78def get_probe_string (func_node ):
89 """Extract the probe string from the decorator of the function node."""
910 # TODO: right now we have the whole string in the section decorator
@@ -38,9 +39,11 @@ def process_func_body(module, builder, func_node, func, ret_type):
3839 elif isinstance (stmt .value , ast .Call ) and isinstance (stmt .value .func , ast .Name ) and len (stmt .value .args ) == 1 and isinstance (stmt .value .args [0 ], ast .Constant ) and isinstance (stmt .value .args [0 ].value , int ):
3940 call_type = stmt .value .func .id
4041 if ctypes_to_ir (call_type ) != ret_type :
41- raise ValueError (f"Return type mismatch: expected { ctypes_to_ir (call_type )} , got { call_type } " )
42+ raise ValueError ("Return type mismatch: expected"
43+ f"{ ctypes_to_ir (call_type )} , got { call_type } " )
4244 else :
43- builder .ret (ir .Constant (ret_type , stmt .value .args [0 ].value ))
45+ builder .ret (ir .Constant (
46+ ret_type , stmt .value .args [0 ].value ))
4447 did_return = True
4548 else :
4649 print ("Unsupported return value" )
@@ -53,8 +56,8 @@ def process_bpf_chunk(func_node, module, return_type):
5356
5457 func_name = func_node .name
5558
56- #TODO: The function actual arg retgurn type is parsed,
57- # but the actual output is not. It's still very wrong. Try uncommenting the
59+ # TODO: The function actual arg retgurn type is parsed,
60+ # but the actual output is not. It's still very wrong. Try uncommenting the
5861 # code in execve2.py once
5962 ret_type = return_type
6063
@@ -89,12 +92,110 @@ def process_bpf_chunk(func_node, module, return_type):
8992 return func
9093
9194
95+ def create_bpf_map (module , map_name , map_params ):
96+ """Create a BPF map in the module with the given parameters"""
97+
98+ type_mapping = {
99+ 'c_uint32' : ir .IntType (32 ),
100+ 'c_uint64' : ir .IntType (64 ),
101+ 'c_int32' : ir .IntType (32 ),
102+ 'c_int64' : ir .IntType (64 ),
103+ # Add more mappings as needed
104+ }
105+
106+ key_type_str = map_params .get ('key_type' , 'c_uint32' )
107+ value_type_str = map_params .get ('value_type' , 'c_uint32' )
108+
109+ key_type = type_mapping .get (key_type_str , ir .IntType (32 ))
110+ value_type = type_mapping .get (value_type_str , ir .IntType (32 ))
111+
112+ map_struct_type = ir .LiteralStructType ([
113+ ir .PointerType (), # type
114+ ir .PointerType (), # max_entries
115+ ir .PointerType (), # key_type
116+ ir .PointerType () # value_type
117+ ])
118+
119+ map_global = ir .GlobalVariable (module , map_struct_type , name = map_name )
120+ map_global .linkage = 'external'
121+ map_global .initializer = ir .Constant (
122+ map_struct_type , [None , None , None , None ])
123+ map_global .section = ".maps"
124+ map_global .align = 8
125+
126+ # TODO: Store map parameters in metadata or a suitable structure
127+ # maps[map_name] = {
128+ # 'global': map_global,
129+ # 'key_type': key_type,
130+ # 'value_type': value_type,
131+ # 'max_entries': map_params.get('max_entries', 1),
132+ # 'map_type': map_params.get('map_type', 'BPF_MAP_TYPE_HASH')
133+ # }
134+
135+ print (f"Created BPF map: { map_name } " )
136+ return map_global
137+
138+
139+ def process_bpf_global (func_node , module ):
140+ """Process a BPF global (a function decorated with @bpfglobal)"""
141+ global_name = func_node .name
142+ print (f"Processing BPF global: { global_name } " )
143+
144+ # For now, assume single return statement
145+ return_stmt = None
146+ for stmt in func_node .body :
147+ if isinstance (stmt , ast .Return ):
148+ return_stmt = stmt
149+ break
150+ if return_stmt is None :
151+ raise ValueError ("BPF global must have a return statement" )
152+
153+ rval = return_stmt .value
154+
155+ # For now, just handle maps
156+ if isinstance (rval , ast .Call ) and isinstance (rval .func , ast .Name ) and rval .func .id == "HashMap" :
157+ print (f"Creating HashMap global: { global_name } " )
158+ map_params = {'map_type' : 'HASH' }
159+ # Handle positional arguments
160+ if rval .args :
161+ # Assuming order is: key_type, value_type, max_entries
162+ if len (rval .args ) >= 1 and isinstance (rval .args [0 ], ast .Name ):
163+ map_params ['key_type' ] = rval .args [0 ].id
164+ if len (rval .args ) >= 2 and isinstance (rval .args [1 ], ast .Name ):
165+ map_params ['value_type' ] = rval .args [1 ].id
166+ if len (rval .args ) >= 3 and isinstance (rval .args [2 ], ast .Constant ):
167+ map_params ['max_entries' ] = rval .args [2 ].value
168+
169+ # Handle keyword arguments (these will override any positional args)
170+ for keyword in rval .keywords :
171+ if keyword .arg == "key_type" and isinstance (keyword .value , ast .Name ):
172+ map_params ['key_type' ] = keyword .value .id
173+ elif keyword .arg == "value_type" and isinstance (keyword .value , ast .Name ):
174+ map_params ['value_type' ] = keyword .value .id
175+ elif keyword .arg == "max_entries" and isinstance (keyword .value , ast .Constant ):
176+ map_params ['max_entries' ] = keyword .value .value
177+ print (f"Map parameters: { map_params } " )
178+ print (create_bpf_map (module , global_name , map_params ))
179+
180+
92181def func_proc (tree , module , chunks ):
93182 for func_node in chunks :
183+ # Check if this function is a global
184+ is_global = False
185+ for decorator in func_node .decorator_list :
186+ if isinstance (decorator , ast .Name ) and decorator .id == "bpfglobal" :
187+ is_global = True
188+ break
189+ if is_global :
190+ print (f"Found BPF global: { func_node .name } " )
191+ process_bpf_global (func_node , module )
192+ continue
94193 func_type = get_probe_string (func_node )
95194 print (f"Found probe_string of { func_node .name } : { func_type } " )
96195
97- process_bpf_chunk (func_node , module , ctypes_to_ir (infer_return_type (func_node )))
196+ process_bpf_chunk (func_node , module , ctypes_to_ir (
197+ infer_return_type (func_node )))
198+
98199
99200def infer_return_type (func_node : ast .FunctionDef ):
100201 if not isinstance (func_node , (ast .FunctionDef , ast .AsyncFunctionDef )):
@@ -113,6 +214,7 @@ def infer_return_type(func_node: ast.FunctionDef):
113214 except Exception :
114215 return type (node ).__name__
115216 found_type = None
217+
116218 def _expr_type (e ):
117219 if e is None :
118220 return "None"
@@ -148,5 +250,6 @@ def _expr_type(e):
148250 if found_type is None :
149251 found_type = t
150252 elif found_type != t :
151- raise ValueError (f"Conflicting return types: { found_type } vs { t } " )
253+ raise ValueError ("Conflicting return types:"
254+ f"{ found_type } vs { t } " )
152255 return found_type or "None"
0 commit comments