Skip to content

Commit de5cc43

Browse files
committed
Allow access from struct fields
1 parent 8c2196c commit de5cc43

4 files changed

Lines changed: 65 additions & 9 deletions

File tree

examples/execve5.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ def hello(ctx: c_void_p) -> c_int32:
2626
ts = ktime()
2727
process_id = pid()
2828
strobj = "hellohellohello"
29-
dataobj.pid = process_id
30-
dataobj.ts = ts
29+
dataobj.pid = pid()
30+
dataobj.ts = ktime()
3131
# dataobj.comm = strobj
32-
print(f"clone called at {ts} by pid {process_id}, comm {strobj}")
32+
print(f"clone called at {dataobj.ts} by pid {dataobj.pid}, comm {strobj}")
3333
events.output(dataobj)
3434
return c_int32(0)
3535

pythonbpf/bpf_helper_handler.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from .expr_pass import eval_expr
44

55

6-
def bpf_ktime_get_ns_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, local_var_metadata=None):
6+
def bpf_ktime_get_ns_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
77
"""
88
Emit LLVM IR for bpf_ktime_get_ns helper function call.
99
"""
@@ -63,7 +63,7 @@ def bpf_map_lookup_elem_emitter(call, map_ptr, module, builder, func, local_sym_
6363
return result, ir.PointerType()
6464

6565

66-
def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, local_var_metadata=None):
66+
def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
6767
if not hasattr(func, "_fmt_counter"):
6868
func._fmt_counter = 0
6969

@@ -101,10 +101,42 @@ def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None,
101101
else:
102102
raise NotImplementedError(
103103
"Only integer and pointer types are supported in formatted values.")
104-
print("Formatted value variable:", var_ptr, var_type)
105104
else:
106105
raise ValueError(
107106
f"Variable {value.value.id} not found in local symbol table.")
107+
elif isinstance(value.value, ast.Attribute):
108+
# object field access from struct
109+
if isinstance(value.value.value, ast.Name) and local_sym_tab and value.value.value.id in local_sym_tab:
110+
var_name = value.value.value.id
111+
field_name = value.value.attr
112+
if local_var_metadata and var_name in local_var_metadata:
113+
var_type = local_var_metadata[var_name]
114+
if var_type in struct_sym_tab:
115+
struct_info = struct_sym_tab[var_type]
116+
if field_name in struct_info["fields"]:
117+
field_index = struct_info["fields"][field_name]
118+
field_type = struct_info["field_types"][field_index]
119+
if isinstance(field_type, ir.IntType):
120+
fmt_parts.append("%lld")
121+
exprs.append(value.value)
122+
elif field_type == ir.PointerType(ir.IntType(8)):
123+
fmt_parts.append("%s")
124+
exprs.append(value.value)
125+
else:
126+
raise NotImplementedError(
127+
"Only integer and pointer types are supported in formatted values.")
128+
else:
129+
raise ValueError(
130+
f"Field {field_name} not found in struct {var_type}.")
131+
else:
132+
raise ValueError(
133+
f"Struct type {var_type} for variable {var_name} not found in struct symbol table.")
134+
else:
135+
raise ValueError(
136+
f"Metadata for variable {var_name} not found in local variable metadata.")
137+
else:
138+
raise ValueError(
139+
f"Variable {value.value.value.id} not found in local symbol table.")
108140
else:
109141
raise NotImplementedError(
110142
"Only simple variable names are supported in formatted values.")
@@ -136,8 +168,9 @@ def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None,
136168
"Warning: bpf_printk supports up to 3 arguments, extra arguments will be ignored.")
137169

138170
for expr in exprs[:3]:
171+
print(f"{ast.dump(expr)}")
139172
val, _ = eval_expr(func, module, builder,
140-
expr, local_sym_tab, None)
173+
expr, local_sym_tab, None, struct_sym_tab, local_var_metadata)
141174
if val:
142175
if isinstance(val.type, ir.PointerType):
143176
val = builder.ptrtoint(val, ir.IntType(64))
@@ -339,7 +372,7 @@ def bpf_map_delete_elem_emitter(call, map_ptr, module, builder, func, local_sym_
339372
return result, None
340373

341374

342-
def bpf_get_current_pid_tgid_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, local_var_metadata=None):
375+
def bpf_get_current_pid_tgid_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
343376
"""
344377
Emit LLVM IR for bpf_get_current_pid_tgid helper function call.
345378
"""
@@ -420,11 +453,12 @@ def bpf_perf_event_output_handler(call, map_ptr, module, builder, func, local_sy
420453

421454

422455
def handle_helper_call(call, module, builder, func, local_sym_tab=None, map_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
456+
print(local_var_metadata)
423457
if isinstance(call.func, ast.Name):
424458
func_name = call.func.id
425459
if func_name in helper_func_list:
426460
# it is not a map method call
427-
return helper_func_list[func_name](call, None, module, builder, func, local_sym_tab)
461+
return helper_func_list[func_name](call, None, module, builder, func, local_sym_tab, struct_sym_tab, local_var_metadata)
428462
else:
429463
raise NotImplementedError(
430464
f"Function {func_name} is not implemented as a helper function.")

pythonbpf/expr_pass.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab=None, local_var_metadata=None):
66
print(f"Evaluating expression: {ast.dump(expr)}")
7+
print(local_var_metadata)
78
if isinstance(expr, ast.Name):
89
if expr.id in local_sym_tab:
910
var = local_sym_tab[expr.id][0]
@@ -66,13 +67,33 @@ def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_s
6667
if method_name in helper_func_list:
6768
return handle_helper_call(
6869
expr, module, builder, func, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata)
70+
elif isinstance(expr, ast.Attribute):
71+
if isinstance(expr.value, ast.Name):
72+
var_name = expr.value.id
73+
attr_name = expr.attr
74+
if var_name in local_sym_tab:
75+
var_ptr, var_type = local_sym_tab[var_name]
76+
print(f"Loading attribute "
77+
f"{attr_name} from variable {var_name}")
78+
print(f"Variable type: {var_type}, Variable ptr: {var_ptr}")
79+
print(local_var_metadata)
80+
if local_var_metadata and var_name in local_var_metadata:
81+
metadata = structs_sym_tab[local_var_metadata[var_name]]
82+
if attr_name in metadata["fields"]:
83+
field_idx = metadata["fields"][attr_name]
84+
gep = builder.gep(var_ptr, [ir.Constant(ir.IntType(32), 0),
85+
ir.Constant(ir.IntType(32), field_idx)])
86+
val = builder.load(gep)
87+
field_type = metadata["field_types"][field_idx]
88+
return val, field_type
6989
print("Unsupported expression evaluation")
7090
return None
7191

7292

7393
def handle_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata):
7494
"""Handle expression statements in the function body."""
7595
print(f"Handling expression: {ast.dump(expr)}")
96+
print(local_var_metadata)
7697
call = expr.value
7798
if isinstance(call, ast.Call):
7899
eval_expr(func, module, builder, call, local_sym_tab,

pythonbpf/functions_pass.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ def handle_if(func, module, builder, stmt, map_sym_tab, local_sym_tab, structs_s
282282
def process_stmt(func, module, builder, stmt, local_sym_tab, map_sym_tab, structs_sym_tab, did_return, ret_type=ir.IntType(64)):
283283
print(f"Processing statement: {ast.dump(stmt)}")
284284
if isinstance(stmt, ast.Expr):
285+
print(local_var_metadata)
285286
handle_expr(func, module, builder, stmt, local_sym_tab,
286287
map_sym_tab, structs_sym_tab, local_var_metadata)
287288
elif isinstance(stmt, ast.Assign):

0 commit comments

Comments
 (0)