mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2025-12-31 21:06:25 +00:00
Compare commits
8 Commits
1cce49f5e0
...
f41693bc6d
| Author | SHA1 | Date | |
|---|---|---|---|
| f41693bc6d | |||
| b7092fa362 | |||
| 0e7dcafbab | |||
| a574527891 | |||
| 176673017c | |||
| 1d6226d829 | |||
| 12b712c217 | |||
| 2de280915a |
1
TODO.md
1
TODO.md
@ -5,6 +5,7 @@
|
||||
- XDP support in pylibbpf
|
||||
- ringbuf support
|
||||
- recursive expression resolution
|
||||
- Add supoprt for BoolOp and short circuiting in conditions
|
||||
|
||||
## Long term
|
||||
|
||||
|
||||
@ -22,7 +22,6 @@ def _handle_name_expr(expr: ast.Name, local_sym_tab: Dict, builder: ir.IRBuilder
|
||||
|
||||
def _handle_constant_expr(expr: ast.Constant):
|
||||
"""Handle ast.Constant expressions."""
|
||||
logger.info("We the best")
|
||||
if isinstance(expr.value, int) or isinstance(expr.value, bool):
|
||||
return ir.Constant(ir.IntType(64), int(expr.value)), ir.IntType(64)
|
||||
else:
|
||||
@ -191,6 +190,43 @@ def _handle_compare(
|
||||
return _handle_comparator(builder, cond.ops[0], lhs, rhs)
|
||||
|
||||
|
||||
def convert_to_bool(builder, val):
|
||||
if val.type == ir.IntType(1):
|
||||
return val
|
||||
if isinstance(val.type, ir.PointerType):
|
||||
zero = ir.Constant(val.type, None)
|
||||
else:
|
||||
zero = ir.Constant(val.type, 0)
|
||||
return builder.icmp_signed("!=", val, zero)
|
||||
|
||||
|
||||
def _handle_unary_op(
|
||||
func,
|
||||
module,
|
||||
builder,
|
||||
expr: ast.UnaryOp,
|
||||
local_sym_tab,
|
||||
map_sym_tab,
|
||||
structs_sym_tab=None,
|
||||
):
|
||||
"""Handle ast.UnaryOp expressions."""
|
||||
if not isinstance(expr.op, ast.Not):
|
||||
logger.error("Only 'not' unary operator is supported")
|
||||
return None
|
||||
|
||||
operand = eval_expr(
|
||||
func, module, builder, expr.operand, local_sym_tab, map_sym_tab, structs_sym_tab
|
||||
)
|
||||
if operand is None:
|
||||
logger.error("Failed to evaluate operand for unary operation")
|
||||
return None
|
||||
|
||||
operand_val, operand_type = operand
|
||||
true_const = ir.Constant(ir.IntType(1), 1)
|
||||
result = builder.xor(convert_to_bool(builder, operand_val), true_const)
|
||||
return result, ir.IntType(1)
|
||||
|
||||
|
||||
def eval_expr(
|
||||
func,
|
||||
module,
|
||||
@ -275,6 +311,10 @@ def eval_expr(
|
||||
return _handle_compare(
|
||||
func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab
|
||||
)
|
||||
elif isinstance(expr, ast.UnaryOp):
|
||||
return _handle_unary_op(
|
||||
func, module, builder, expr, local_sym_tab, map_sym_tab, structs_sym_tab
|
||||
)
|
||||
logger.info("Unsupported expression evaluation")
|
||||
return None
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ from dataclasses import dataclass
|
||||
from pythonbpf.helper import HelperHandlerRegistry, handle_helper_call
|
||||
from pythonbpf.type_deducer import ctypes_to_ir
|
||||
from pythonbpf.binary_ops import handle_binary_op
|
||||
from pythonbpf.expr_pass import eval_expr, handle_expr
|
||||
from pythonbpf.expr_pass import eval_expr, handle_expr, convert_to_bool
|
||||
|
||||
from .return_utils import _handle_none_return, _handle_xdp_return, _is_xdp_name
|
||||
|
||||
@ -240,20 +240,10 @@ def handle_assign(
|
||||
logger.info("Unsupported assignment value type")
|
||||
|
||||
|
||||
def _convert_to_bool(builder, val):
|
||||
if val.type == ir.IntType(1):
|
||||
return val
|
||||
if isinstance(val.type, ir.PointerType):
|
||||
zero = ir.Constant(val.type, None)
|
||||
else:
|
||||
zero = ir.Constant(val.type, 0)
|
||||
return builder.icmp_signed("!=", val, zero)
|
||||
|
||||
|
||||
def handle_cond(func, module, builder, cond, local_sym_tab, map_sym_tab):
|
||||
if True:
|
||||
val = eval_expr(func, module, builder, cond, local_sym_tab, map_sym_tab)[0]
|
||||
return _convert_to_bool(builder, val)
|
||||
return convert_to_bool(builder, val)
|
||||
if isinstance(cond, ast.Constant):
|
||||
if isinstance(cond.value, bool) or isinstance(cond.value, int):
|
||||
return ir.Constant(ir.IntType(1), int(cond.value))
|
||||
|
||||
30
tests/failing_tests/conditionals/map_comp.py
Normal file
30
tests/failing_tests/conditionals/map_comp.py
Normal file
@ -0,0 +1,30 @@
|
||||
from pythonbpf import bpf, map, section, bpfglobal, compile
|
||||
from ctypes import c_void_p, c_int64, c_uint64
|
||||
from pythonbpf.maps import HashMap
|
||||
|
||||
|
||||
@bpf
|
||||
@map
|
||||
def last() -> HashMap:
|
||||
return HashMap(key=c_uint64, value=c_uint64, max_entries=3)
|
||||
|
||||
|
||||
@bpf
|
||||
@section("tracepoint/syscalls/sys_enter_execve")
|
||||
def hello_world(ctx: c_void_p) -> c_int64:
|
||||
last.update(0, 1)
|
||||
tsp = last.lookup(0)
|
||||
if not (tsp > 0):
|
||||
print("Hello, World!")
|
||||
else:
|
||||
print("Goodbye, World!")
|
||||
return
|
||||
|
||||
|
||||
@bpf
|
||||
@bpfglobal
|
||||
def LICENSE() -> str:
|
||||
return "GPL"
|
||||
|
||||
|
||||
compile()
|
||||
29
tests/failing_tests/conditionals/struct_access.py
Normal file
29
tests/failing_tests/conditionals/struct_access.py
Normal file
@ -0,0 +1,29 @@
|
||||
from pythonbpf import bpf, struct, section, bpfglobal, compile
|
||||
from ctypes import c_void_p, c_int64, c_uint64
|
||||
|
||||
|
||||
@bpf
|
||||
@struct
|
||||
class data_t:
|
||||
pid: c_uint64
|
||||
ts: c_uint64
|
||||
|
||||
|
||||
@bpf
|
||||
@section("tracepoint/syscalls/sys_enter_execve")
|
||||
def hello_world(ctx: c_void_p) -> c_int64:
|
||||
dat = data_t()
|
||||
if dat.pid:
|
||||
print("Hello, World!")
|
||||
else:
|
||||
print("Goodbye, World!")
|
||||
return
|
||||
|
||||
|
||||
@bpf
|
||||
@bpfglobal
|
||||
def LICENSE() -> str:
|
||||
return "GPL"
|
||||
|
||||
|
||||
compile()
|
||||
30
tests/passing_tests/conditionals/map.py
Normal file
30
tests/passing_tests/conditionals/map.py
Normal file
@ -0,0 +1,30 @@
|
||||
from pythonbpf import bpf, map, section, bpfglobal, compile
|
||||
from ctypes import c_void_p, c_int64, c_uint64
|
||||
from pythonbpf.maps import HashMap
|
||||
|
||||
|
||||
@bpf
|
||||
@map
|
||||
def last() -> HashMap:
|
||||
return HashMap(key=c_uint64, value=c_uint64, max_entries=3)
|
||||
|
||||
|
||||
@bpf
|
||||
@section("tracepoint/syscalls/sys_enter_execve")
|
||||
def hello_world(ctx: c_void_p) -> c_int64:
|
||||
# last.update(0, 1)
|
||||
tsp = last.lookup(0)
|
||||
if tsp:
|
||||
print("Hello, World!")
|
||||
else:
|
||||
print("Goodbye, World!")
|
||||
return
|
||||
|
||||
|
||||
@bpf
|
||||
@bpfglobal
|
||||
def LICENSE() -> str:
|
||||
return "GPL"
|
||||
|
||||
|
||||
compile()
|
||||
30
tests/passing_tests/conditionals/not.py
Normal file
30
tests/passing_tests/conditionals/not.py
Normal file
@ -0,0 +1,30 @@
|
||||
from pythonbpf import bpf, map, section, bpfglobal, compile
|
||||
from ctypes import c_void_p, c_int64, c_uint64
|
||||
from pythonbpf.maps import HashMap
|
||||
|
||||
|
||||
@bpf
|
||||
@map
|
||||
def last() -> HashMap:
|
||||
return HashMap(key=c_uint64, value=c_uint64, max_entries=3)
|
||||
|
||||
|
||||
@bpf
|
||||
@section("tracepoint/syscalls/sys_enter_execve")
|
||||
def hello_world(ctx: c_void_p) -> c_int64:
|
||||
# last.update(0, 1)
|
||||
tsp = last.lookup(0)
|
||||
if not tsp:
|
||||
print("Hello, World!")
|
||||
else:
|
||||
print("Goodbye, World!")
|
||||
return
|
||||
|
||||
|
||||
@bpf
|
||||
@bpfglobal
|
||||
def LICENSE() -> str:
|
||||
return "GPL"
|
||||
|
||||
|
||||
compile()
|
||||
22
tests/passing_tests/conditionals/var.py
Normal file
22
tests/passing_tests/conditionals/var.py
Normal file
@ -0,0 +1,22 @@
|
||||
from pythonbpf import bpf, section, bpfglobal, compile
|
||||
from ctypes import c_void_p, c_int64
|
||||
|
||||
|
||||
@bpf
|
||||
@section("tracepoint/syscalls/sys_enter_execve")
|
||||
def hello_world(ctx: c_void_p) -> c_int64:
|
||||
x = 0
|
||||
if x:
|
||||
print("Hello, World!")
|
||||
else:
|
||||
print("Goodbye, World!")
|
||||
return
|
||||
|
||||
|
||||
@bpf
|
||||
@bpfglobal
|
||||
def LICENSE() -> str:
|
||||
return "GPL"
|
||||
|
||||
|
||||
compile()
|
||||
22
tests/passing_tests/conditionals/var_binop.py
Normal file
22
tests/passing_tests/conditionals/var_binop.py
Normal file
@ -0,0 +1,22 @@
|
||||
from pythonbpf import bpf, section, bpfglobal, compile
|
||||
from ctypes import c_void_p, c_int64
|
||||
|
||||
|
||||
@bpf
|
||||
@section("tracepoint/syscalls/sys_enter_execve")
|
||||
def hello_world(ctx: c_void_p) -> c_int64:
|
||||
x = 0
|
||||
if x * 1:
|
||||
print("Hello, World!")
|
||||
else:
|
||||
print("Goodbye, World!")
|
||||
return
|
||||
|
||||
|
||||
@bpf
|
||||
@bpfglobal
|
||||
def LICENSE() -> str:
|
||||
return "GPL"
|
||||
|
||||
|
||||
compile()
|
||||
22
tests/passing_tests/conditionals/var_comp.py
Normal file
22
tests/passing_tests/conditionals/var_comp.py
Normal file
@ -0,0 +1,22 @@
|
||||
from pythonbpf import bpf, section, bpfglobal, compile
|
||||
from ctypes import c_void_p, c_int64
|
||||
|
||||
|
||||
@bpf
|
||||
@section("tracepoint/syscalls/sys_enter_execve")
|
||||
def hello_world(ctx: c_void_p) -> c_int64:
|
||||
x = 2
|
||||
if x > 3:
|
||||
print("Hello, World!")
|
||||
else:
|
||||
print("Goodbye, World!")
|
||||
return
|
||||
|
||||
|
||||
@bpf
|
||||
@bpfglobal
|
||||
def LICENSE() -> str:
|
||||
return "GPL"
|
||||
|
||||
|
||||
compile()
|
||||
Reference in New Issue
Block a user