Initialize PythonBPF project and toolchain

This commit is contained in:
2025-08-30 18:08:14 +05:30
commit d5557d3c01
10 changed files with 119 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
*venv*/
.ropeproject/
.idea/
*.egg-info/
.vscode/
__pycache__/
*.ll
*.o

14
Makefile Normal file
View File

@ -0,0 +1,14 @@
install:
pip install -e .
compile:
chmod +x ./tools/compile.py
./tools/compile.py ./examples/execve.py
clean:
rm -rf build dist *.egg-info
rm -rf examples/execve.ll examples/execve.o
all: install compile
.PHONY: all clean

0
README.md Normal file
View File

11
examples/example.bpf.c Normal file
View File

@ -0,0 +1,11 @@
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
SEC("tracepoint/syscalls/sys_enter_execve")
int trace_execve(void *ctx)
{
bpf_printk("execve called\n");
return 0;
}
char LICENSE[] SEC("license") = "GPL";

10
examples/execve.py Normal file
View File

@ -0,0 +1,10 @@
from pythonbpf import decorators
@decorators.tracepoint("syscalls:sys_enter_execve")
def trace_execve(ctx) -> int:
decorators.trace_printk("execve called\n")
return 0
@decorators.license("GPL")
def _():
pass

22
pyproject.toml Normal file
View File

@ -0,0 +1,22 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "pythonbpf"
version = "0.1.0"
description = "Reduced Python frontend for eBPF"
authors = [
{ name = "r41k0u" },
{ name = "varun-r-mallya" }
]
requires-python = ">=3.8"
dependencies = [
"llvmlite",
"astpretty"
]
[tool.setuptools.packages.find]
where = ["."]
include = ["pythonbpf*"]

0
pythonbpf/__init__.py Normal file
View File

19
pythonbpf/codegen.py Normal file
View File

@ -0,0 +1,19 @@
import ast
from llvmlite import ir
def compile_to_ir(filename: str, output: str):
with open(filename) as f:
ast.parse(f.read(), filename)
module = ir.Module(name="pythonbpf")
func_ty = ir.FunctionType(ir.IntType(64), [], False)
func = ir.Function(module, func_ty, name="trace_execve")
block = func.append_basic_block(name="entry")
builder = ir.IRBuilder(block)
builder.ret(ir.IntType(64)(0))
with open(output, "w") as f:
f.write(str(module))
return output

15
pythonbpf/decorators.py Normal file
View File

@ -0,0 +1,15 @@
def tracepoint(name: str):
def wrapper(fn):
fn._section = f"tracepoint/{name}"
return fn
return wrapper
def license(name: str):
def wrapper(fn):
fn._license = name
return fn
return wrapper
def trace_printk(msg: str):
# placeholder — real version lowers to IR later
print(f"[trace_printk] {msg}")

20
tools/compile.py Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
import argparse, subprocess, os
from pythonbpf import codegen
def main():
parser = argparse.ArgumentParser()
parser.add_argument("source", help="Python BPF program")
args = parser.parse_args()
ll_file = os.path.splitext(args.source)[0] + ".ll"
o_file = os.path.splitext(args.source)[0] + ".o"
print(f"[+] Compiling {args.source}{ll_file}")
codegen.compile_to_ir(args.source, ll_file)
print("[+] Running llc -march=bpf")
subprocess.run(["llc", "-march=bpf", "-filetype=obj", ll_file, "-o", o_file], check=True)
if __name__ == "__main__":
main()