From 581269e52b784cdee4b05bf0f13d631ed4c730ac Mon Sep 17 00:00:00 2001 From: Pragyansh Chaturvedi Date: Wed, 28 Jan 2026 16:34:48 +0530 Subject: [PATCH] docs: Fix user-guide/compilation --- docs/user-guide/compilation.md | 123 ++++----------------------------- 1 file changed, 13 insertions(+), 110 deletions(-) diff --git a/docs/user-guide/compilation.md b/docs/user-guide/compilation.md index 46b0efd..0a58f2e 100644 --- a/docs/user-guide/compilation.md +++ b/docs/user-guide/compilation.md @@ -6,10 +6,9 @@ PythonBPF provides several functions and classes for compiling Python code into The compilation process transforms Python code into executable BPF programs: -1. **Python Source** → AST parsing -2. **AST** → LLVM IR generation (using llvmlite) -3. **LLVM IR** → BPF bytecode (using llc) -4. **BPF Object** → Kernel loading (using libbpf) +1. **Python AST** → LLVM IR generation (using llvmlite) +2. **LLVM IR** → BPF bytecode (using llc) +3. **BPF Object** → Kernel loading (using libbpf) ## Compilation Functions @@ -20,14 +19,14 @@ Compile Python source to LLVM Intermediate Representation. #### Signature ```python -def compile_to_ir(filename: str, output: str, loglevel=logging.INFO) +def compile_to_ir(filename: str, output: str, loglevel=logging.WARNING) ``` #### Parameters * `filename` - Path to the Python source file to compile * `output` - Path where the LLVM IR file (.ll) should be written -* `loglevel` - Logging level (default: `logging.INFO`) +* `loglevel` - Logging level (default: `logging.WARNING`) #### Usage @@ -49,22 +48,6 @@ This function generates an `.ll` file containing LLVM IR, which is human-readabl * Debugging compilation issues * Understanding code generation -* Manual optimization -* Educational purposes - -#### Example IR Output - -```llvm -; ModuleID = 'bpf_module' -source_filename = "bpf_module" -target triple = "bpf" - -define i64 @hello_world(i8* %ctx) { -entry: - ; BPF code here - ret i64 0 -} -``` ### compile() @@ -73,14 +56,14 @@ Compile Python source to BPF object file. #### Signature ```python -def compile(filename: str = None, output: str = None, loglevel=logging.INFO) +def compile(filename: str = None, output: str = None, loglevel=logging.WARNING) ``` #### Parameters * `filename` - Path to the Python source file (default: calling file) * `output` - Path for the output object file (default: same name with `.o` extension) -* `loglevel` - Logging level (default: `logging.INFO`) +* `loglevel` - Logging level (default: `logging.WARNING`) #### Usage @@ -107,17 +90,6 @@ This function generates a `.o` file containing BPF bytecode that can be: * Verified with the BPF verifier * Distributed as a compiled binary -#### Compilation Steps - -The `compile()` function performs these steps: - -1. Parse Python source to AST -2. Process decorators and find BPF functions -3. Generate LLVM IR -4. Write IR to temporary `.ll` file -5. Invoke `llc` to compile to BPF object -6. Write final `.o` file - ### BPF Class The `BPF` class provides a high-level interface to compile, load, and attach BPF programs. @@ -126,7 +98,7 @@ The `BPF` class provides a high-level interface to compile, load, and attach BPF ```python class BPF: - def __init__(self, filename: str = None, loglevel=logging.INFO) + def __init__(self, filename: str = None, loglevel=logging.WARNING) def load(self) def attach_all(self) def load_and_attach(self) @@ -135,7 +107,7 @@ class BPF: #### Parameters * `filename` - Path to Python source file (default: calling file) -* `loglevel` - Logging level (default: `logging.INFO`) +* `loglevel` - Logging level (default: `logging.WARNING`) #### Methods @@ -212,7 +184,7 @@ from ctypes import c_void_p, c_int64 @section("tracepoint/syscalls/sys_enter_execve") def trace_exec(ctx: c_void_p) -> c_int64: print("Process started") - return c_int64(0) + return 0 @bpf @bpfglobal @@ -224,13 +196,13 @@ if __name__ == "__main__": b = BPF() b.load_and_attach() trace_pipe() - + # Method 2: Step-by-step # b = BPF() # b.load() # b.attach_all() # trace_pipe() - + # Method 3: Manual compilation # from pythonbpf import compile # compile(filename="my_program.py", output="my_program.o") @@ -285,11 +257,6 @@ The LLVM IR is compiled to BPF bytecode using `llc`: llc -march=bpf -filetype=obj input.ll -o output.o ``` -Compiler flags: -* `-march=bpf` - Target BPF architecture -* `-filetype=obj` - Generate object file -* `-O2` - Optimization level (sometimes used) - ### Kernel Loading The compiled object is loaded using `pylibbpf`: @@ -301,13 +268,6 @@ obj = BpfObject(path="program.o") obj.load() ``` -The kernel verifier checks: -* Memory access patterns -* Pointer usage -* Loop bounds -* Instruction count -* Helper function calls - ## Debugging Compilation ### Logging @@ -364,24 +324,11 @@ bpftool map dump id If the kernel verifier rejects your program: -1. Check `dmesg` for detailed error messages: +* Check `dmesg` for detailed error messages: ```bash sudo dmesg | tail -50 ``` -2. Common issues: - * Unbounded loops - * Invalid pointer arithmetic - * Exceeding instruction limit - * Invalid helper calls - * License incompatibility - -3. Solutions: - * Simplify logic - * Use bounded loops - * Check pointer operations - * Verify GPL license - ## Compilation Options ### Optimization Levels @@ -395,20 +342,11 @@ While PythonBPF doesn't expose optimization flags directly, you can: 2. Modify the compilation pipeline in your code -### Target Options - -BPF compilation targets the BPF architecture: - -* **Architecture**: `bpf` -* **Endianness**: Typically little-endian -* **Pointer size**: 64-bit - ### Debug Information PythonBPF automatically generates debug information (DWARF) for: * Function names -* Line numbers * Variable names * Type information @@ -461,41 +399,6 @@ BPF objects are generally compatible across kernel versions, but: * Helper functions may not be available on older kernels * BTF (BPF Type Format) requirements vary -## Best Practices - -1. **Keep compilation separate from runtime** - ```python - if __name__ == "__main__": - b = BPF() - b.load_and_attach() - # Runtime code - ``` - -2. **Handle compilation errors gracefully** - ```python - try: - b = BPF() - b.load() - except Exception as e: - print(f"Failed to load BPF program: {e}") - exit(1) - ``` - -3. **Use appropriate logging levels** - * `DEBUG` for development - * `INFO` for production - * `ERROR` for critical issues - -4. **Cache compiled objects** - * Compile once, load many times - * Store `.o` files for reuse - * Version your compiled objects - -5. **Test incrementally** - * Compile after each change - * Verify programs load successfully - * Test attachment before full deployment - ## Troubleshooting ### Compilation Fails