55from .maps import maps_proc
66from .structs import structs_proc
77from .globals_pass import globals_processing
8- from .debuginfo import DW_LANG_C11 , DwarfBehaviorEnum
8+ from .debuginfo import DW_LANG_C11 , DwarfBehaviorEnum , DebugInfoGenerator
99import os
1010import subprocess
1111import inspect
1212from pathlib import Path
1313from pylibbpf import BpfProgram
1414import tempfile
15+ from logging import Logger
16+ import logging
1517
16- VERSION = "v0.1.3"
18+ logger : Logger = logging .getLogger (__name__ )
19+
20+ VERSION = "v0.1.4"
1721
1822
1923def find_bpf_chunks (tree ):
@@ -30,11 +34,11 @@ def find_bpf_chunks(tree):
3034
3135def processor (source_code , filename , module ):
3236 tree = ast .parse (source_code , filename )
33- print (ast .dump (tree , indent = 4 ))
37+ logger . debug (ast .dump (tree , indent = 4 ))
3438
3539 bpf_chunks = find_bpf_chunks (tree )
3640 for func_node in bpf_chunks :
37- print (f"Found BPF function/struct: { func_node .name } " )
41+ logger . info (f"Found BPF function/struct: { func_node .name } " )
3842
3943 structs_sym_tab = structs_proc (tree , module , bpf_chunks )
4044 map_sym_tab = maps_proc (tree , module , bpf_chunks )
@@ -44,7 +48,10 @@ def processor(source_code, filename, module):
4448 globals_processing (tree , module )
4549
4650
47- def compile_to_ir (filename : str , output : str ):
51+ def compile_to_ir (filename : str , output : str , loglevel = logging .WARNING ):
52+ logging .basicConfig (
53+ level = loglevel , format = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
54+ )
4855 with open (filename ) as f :
4956 source = f .read ()
5057
@@ -53,33 +60,17 @@ def compile_to_ir(filename: str, output: str):
5360 module .triple = "bpf"
5461
5562 if not hasattr (module , "_debug_compile_unit" ):
56- module ._file_metadata = module .add_debug_info (
57- "DIFile" ,
58- { # type: ignore
59- "filename" : filename ,
60- "directory" : os .path .dirname (filename ),
61- },
62- )
63-
64- module ._debug_compile_unit = module .add_debug_info (
65- "DICompileUnit" ,
66- { # type: ignore
67- "language" : DW_LANG_C11 ,
68- "file" : module ._file_metadata , # type: ignore
69- "producer" : f"PythonBPF { VERSION } " ,
70- "isOptimized" : True , # TODO: This is probably not true
71- # TODO: add a global field here that keeps track of all the globals. Works without it, but I think it might
72- # be required for kprobes.
73- "runtimeVersion" : 0 ,
74- "emissionKind" : 1 ,
75- "splitDebugInlining" : False ,
76- "nameTableKind" : 0 ,
77- },
78- is_distinct = True ,
63+ debug_generator = DebugInfoGenerator (module )
64+ debug_generator .generate_file_metadata (filename , os .path .dirname (filename ))
65+ debug_generator .generate_debug_cu (
66+ DW_LANG_C11 ,
67+ f"PythonBPF { VERSION } " ,
68+ True , # TODO: This is probably not true
69+ # TODO: add a global field here that keeps track of all the globals. Works without it, but I think it might
70+ # be required for kprobes.
71+ True ,
7972 )
8073
81- module .add_named_metadata ("llvm.dbg.cu" , module ._debug_compile_unit ) # type: ignore
82-
8374 processor (source , filename , module )
8475
8576 wchar_size = module .add_metadata (
@@ -121,7 +112,7 @@ def compile_to_ir(filename: str, output: str):
121112
122113 module .add_named_metadata ("llvm.ident" , [f"PythonBPF { VERSION } " ])
123114
124- print (f"IR written to { output } " )
115+ logger . info (f"IR written to { output } " )
125116 with open (output , "w" ) as f :
126117 f .write (f'source_filename = "{ filename } "\n ' )
127118 f .write (str (module ))
@@ -130,7 +121,7 @@ def compile_to_ir(filename: str, output: str):
130121 return output
131122
132123
133- def compile () -> bool :
124+ def compile (loglevel = logging . WARNING ) -> bool :
134125 # Look one level up the stack to the caller of this function
135126 caller_frame = inspect .stack ()[1 ]
136127 caller_file = Path (caller_frame .filename ).resolve ()
@@ -139,7 +130,9 @@ def compile() -> bool:
139130 o_file = caller_file .with_suffix (".o" )
140131
141132 success = True
142- success = compile_to_ir (str (caller_file ), str (ll_file )) and success
133+ success = (
134+ compile_to_ir (str (caller_file ), str (ll_file ), loglevel = loglevel ) and success
135+ )
143136
144137 success = bool (
145138 subprocess .run (
@@ -157,11 +150,11 @@ def compile() -> bool:
157150 and success
158151 )
159152
160- print (f"Object written to { o_file } " )
153+ logger . info (f"Object written to { o_file } " )
161154 return success
162155
163156
164- def BPF () -> BpfProgram :
157+ def BPF (loglevel = logging . WARNING ) -> BpfProgram :
165158 caller_frame = inspect .stack ()[1 ]
166159 src = inspect .getsource (caller_frame .frame )
167160 with tempfile .NamedTemporaryFile (
@@ -174,7 +167,7 @@ def BPF() -> BpfProgram:
174167 f .write (src )
175168 f .flush ()
176169 source = f .name
177- compile_to_ir (source , str (inter .name ))
170+ compile_to_ir (source , str (inter .name ), loglevel = loglevel )
178171 subprocess .run (
179172 [
180173 "llc" ,
0 commit comments