mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2025-12-31 21:06:25 +00:00
Allow access from struct fields
This commit is contained in:
@ -26,10 +26,10 @@ def hello(ctx: c_void_p) -> c_int32:
|
|||||||
ts = ktime()
|
ts = ktime()
|
||||||
process_id = pid()
|
process_id = pid()
|
||||||
strobj = "hellohellohello"
|
strobj = "hellohellohello"
|
||||||
dataobj.pid = process_id
|
dataobj.pid = pid()
|
||||||
dataobj.ts = ts
|
dataobj.ts = ktime()
|
||||||
# dataobj.comm = strobj
|
# dataobj.comm = strobj
|
||||||
print(f"clone called at {ts} by pid {process_id}, comm {strobj}")
|
print(f"clone called at {dataobj.ts} by pid {dataobj.pid}, comm {strobj}")
|
||||||
events.output(dataobj)
|
events.output(dataobj)
|
||||||
return c_int32(0)
|
return c_int32(0)
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ from llvmlite import ir
|
|||||||
from .expr_pass import eval_expr
|
from .expr_pass import eval_expr
|
||||||
|
|
||||||
|
|
||||||
def bpf_ktime_get_ns_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, local_var_metadata=None):
|
def bpf_ktime_get_ns_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
|
||||||
"""
|
"""
|
||||||
Emit LLVM IR for bpf_ktime_get_ns helper function call.
|
Emit LLVM IR for bpf_ktime_get_ns helper function call.
|
||||||
"""
|
"""
|
||||||
@ -63,7 +63,7 @@ def bpf_map_lookup_elem_emitter(call, map_ptr, module, builder, func, local_sym_
|
|||||||
return result, ir.PointerType()
|
return result, ir.PointerType()
|
||||||
|
|
||||||
|
|
||||||
def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, local_var_metadata=None):
|
def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
|
||||||
if not hasattr(func, "_fmt_counter"):
|
if not hasattr(func, "_fmt_counter"):
|
||||||
func._fmt_counter = 0
|
func._fmt_counter = 0
|
||||||
|
|
||||||
@ -101,10 +101,42 @@ def bpf_printk_emitter(call, map_ptr, module, builder, func, local_sym_tab=None,
|
|||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Only integer and pointer types are supported in formatted values.")
|
"Only integer and pointer types are supported in formatted values.")
|
||||||
print("Formatted value variable:", var_ptr, var_type)
|
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Variable {value.value.id} not found in local symbol table.")
|
f"Variable {value.value.id} not found in local symbol table.")
|
||||||
|
elif isinstance(value.value, ast.Attribute):
|
||||||
|
# object field access from struct
|
||||||
|
if isinstance(value.value.value, ast.Name) and local_sym_tab and value.value.value.id in local_sym_tab:
|
||||||
|
var_name = value.value.value.id
|
||||||
|
field_name = value.value.attr
|
||||||
|
if local_var_metadata and var_name in local_var_metadata:
|
||||||
|
var_type = local_var_metadata[var_name]
|
||||||
|
if var_type in struct_sym_tab:
|
||||||
|
struct_info = struct_sym_tab[var_type]
|
||||||
|
if field_name in struct_info["fields"]:
|
||||||
|
field_index = struct_info["fields"][field_name]
|
||||||
|
field_type = struct_info["field_types"][field_index]
|
||||||
|
if isinstance(field_type, ir.IntType):
|
||||||
|
fmt_parts.append("%lld")
|
||||||
|
exprs.append(value.value)
|
||||||
|
elif field_type == ir.PointerType(ir.IntType(8)):
|
||||||
|
fmt_parts.append("%s")
|
||||||
|
exprs.append(value.value)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(
|
||||||
|
"Only integer and pointer types are supported in formatted values.")
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Field {field_name} not found in struct {var_type}.")
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Struct type {var_type} for variable {var_name} not found in struct symbol table.")
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Metadata for variable {var_name} not found in local variable metadata.")
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Variable {value.value.value.id} not found in local symbol table.")
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Only simple variable names are supported in formatted values.")
|
"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,
|
|||||||
"Warning: bpf_printk supports up to 3 arguments, extra arguments will be ignored.")
|
"Warning: bpf_printk supports up to 3 arguments, extra arguments will be ignored.")
|
||||||
|
|
||||||
for expr in exprs[:3]:
|
for expr in exprs[:3]:
|
||||||
|
print(f"{ast.dump(expr)}")
|
||||||
val, _ = eval_expr(func, module, builder,
|
val, _ = eval_expr(func, module, builder,
|
||||||
expr, local_sym_tab, None)
|
expr, local_sym_tab, None, struct_sym_tab, local_var_metadata)
|
||||||
if val:
|
if val:
|
||||||
if isinstance(val.type, ir.PointerType):
|
if isinstance(val.type, ir.PointerType):
|
||||||
val = builder.ptrtoint(val, ir.IntType(64))
|
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_
|
|||||||
return result, None
|
return result, None
|
||||||
|
|
||||||
|
|
||||||
def bpf_get_current_pid_tgid_emitter(call, map_ptr, module, builder, func, local_sym_tab=None, local_var_metadata=None):
|
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):
|
||||||
"""
|
"""
|
||||||
Emit LLVM IR for bpf_get_current_pid_tgid helper function call.
|
Emit LLVM IR for bpf_get_current_pid_tgid helper function call.
|
||||||
"""
|
"""
|
||||||
@ -420,11 +453,12 @@ helper_func_list = {
|
|||||||
|
|
||||||
|
|
||||||
def handle_helper_call(call, module, builder, func, local_sym_tab=None, map_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
|
def handle_helper_call(call, module, builder, func, local_sym_tab=None, map_sym_tab=None, struct_sym_tab=None, local_var_metadata=None):
|
||||||
|
print(local_var_metadata)
|
||||||
if isinstance(call.func, ast.Name):
|
if isinstance(call.func, ast.Name):
|
||||||
func_name = call.func.id
|
func_name = call.func.id
|
||||||
if func_name in helper_func_list:
|
if func_name in helper_func_list:
|
||||||
# it is not a map method call
|
# it is not a map method call
|
||||||
return helper_func_list[func_name](call, None, module, builder, func, local_sym_tab)
|
return helper_func_list[func_name](call, None, module, builder, func, local_sym_tab, struct_sym_tab, local_var_metadata)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
f"Function {func_name} is not implemented as a helper function.")
|
f"Function {func_name} is not implemented as a helper function.")
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from llvmlite import ir
|
|||||||
|
|
||||||
def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab=None, local_var_metadata=None):
|
def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab=None, local_var_metadata=None):
|
||||||
print(f"Evaluating expression: {ast.dump(expr)}")
|
print(f"Evaluating expression: {ast.dump(expr)}")
|
||||||
|
print(local_var_metadata)
|
||||||
if isinstance(expr, ast.Name):
|
if isinstance(expr, ast.Name):
|
||||||
if expr.id in local_sym_tab:
|
if expr.id in local_sym_tab:
|
||||||
var = local_sym_tab[expr.id][0]
|
var = local_sym_tab[expr.id][0]
|
||||||
@ -66,6 +67,25 @@ def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_s
|
|||||||
if method_name in helper_func_list:
|
if method_name in helper_func_list:
|
||||||
return handle_helper_call(
|
return handle_helper_call(
|
||||||
expr, module, builder, func, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata)
|
expr, module, builder, func, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata)
|
||||||
|
elif isinstance(expr, ast.Attribute):
|
||||||
|
if isinstance(expr.value, ast.Name):
|
||||||
|
var_name = expr.value.id
|
||||||
|
attr_name = expr.attr
|
||||||
|
if var_name in local_sym_tab:
|
||||||
|
var_ptr, var_type = local_sym_tab[var_name]
|
||||||
|
print(f"Loading attribute "
|
||||||
|
f"{attr_name} from variable {var_name}")
|
||||||
|
print(f"Variable type: {var_type}, Variable ptr: {var_ptr}")
|
||||||
|
print(local_var_metadata)
|
||||||
|
if local_var_metadata and var_name in local_var_metadata:
|
||||||
|
metadata = structs_sym_tab[local_var_metadata[var_name]]
|
||||||
|
if attr_name in metadata["fields"]:
|
||||||
|
field_idx = metadata["fields"][attr_name]
|
||||||
|
gep = builder.gep(var_ptr, [ir.Constant(ir.IntType(32), 0),
|
||||||
|
ir.Constant(ir.IntType(32), field_idx)])
|
||||||
|
val = builder.load(gep)
|
||||||
|
field_type = metadata["field_types"][field_idx]
|
||||||
|
return val, field_type
|
||||||
print("Unsupported expression evaluation")
|
print("Unsupported expression evaluation")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -73,6 +93,7 @@ def eval_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_s
|
|||||||
def handle_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata):
|
def handle_expr(func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab, local_var_metadata):
|
||||||
"""Handle expression statements in the function body."""
|
"""Handle expression statements in the function body."""
|
||||||
print(f"Handling expression: {ast.dump(expr)}")
|
print(f"Handling expression: {ast.dump(expr)}")
|
||||||
|
print(local_var_metadata)
|
||||||
call = expr.value
|
call = expr.value
|
||||||
if isinstance(call, ast.Call):
|
if isinstance(call, ast.Call):
|
||||||
eval_expr(func, module, builder, call, local_sym_tab,
|
eval_expr(func, module, builder, call, local_sym_tab,
|
||||||
|
|||||||
@ -282,6 +282,7 @@ def handle_if(func, module, builder, stmt, map_sym_tab, local_sym_tab, structs_s
|
|||||||
def process_stmt(func, module, builder, stmt, local_sym_tab, map_sym_tab, structs_sym_tab, did_return, ret_type=ir.IntType(64)):
|
def process_stmt(func, module, builder, stmt, local_sym_tab, map_sym_tab, structs_sym_tab, did_return, ret_type=ir.IntType(64)):
|
||||||
print(f"Processing statement: {ast.dump(stmt)}")
|
print(f"Processing statement: {ast.dump(stmt)}")
|
||||||
if isinstance(stmt, ast.Expr):
|
if isinstance(stmt, ast.Expr):
|
||||||
|
print(local_var_metadata)
|
||||||
handle_expr(func, module, builder, stmt, local_sym_tab,
|
handle_expr(func, module, builder, stmt, local_sym_tab,
|
||||||
map_sym_tab, structs_sym_tab, local_var_metadata)
|
map_sym_tab, structs_sym_tab, local_var_metadata)
|
||||||
elif isinstance(stmt, ast.Assign):
|
elif isinstance(stmt, ast.Assign):
|
||||||
|
|||||||
Reference in New Issue
Block a user