docs: Fix user-guide/compilation

This commit is contained in:
Pragyansh Chaturvedi
2026-01-28 16:34:48 +05:30
parent 8bfd998863
commit 581269e52b

View File

@ -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: The compilation process transforms Python code into executable BPF programs:
1. **Python Source** → AST parsing 1. **Python AST** → LLVM IR generation (using llvmlite)
2. **AST** → LLVM IR generation (using llvmlite) 2. **LLVM IR** → BPF bytecode (using llc)
3. **LLVM IR** → BPF bytecode (using llc) 3. **BPF Object** → Kernel loading (using libbpf)
4. **BPF Object** → Kernel loading (using libbpf)
## Compilation Functions ## Compilation Functions
@ -20,14 +19,14 @@ Compile Python source to LLVM Intermediate Representation.
#### Signature #### Signature
```python ```python
def compile_to_ir(filename: str, output: str, loglevel=logging.INFO) def compile_to_ir(filename: str, output: str, loglevel=logging.WARNING)
``` ```
#### Parameters #### Parameters
* `filename` - Path to the Python source file to compile * `filename` - Path to the Python source file to compile
* `output` - Path where the LLVM IR file (.ll) should be written * `output` - Path where the LLVM IR file (.ll) should be written
* `loglevel` - Logging level (default: `logging.INFO`) * `loglevel` - Logging level (default: `logging.WARNING`)
#### Usage #### Usage
@ -49,22 +48,6 @@ This function generates an `.ll` file containing LLVM IR, which is human-readabl
* Debugging compilation issues * Debugging compilation issues
* Understanding code generation * 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() ### compile()
@ -73,14 +56,14 @@ Compile Python source to BPF object file.
#### Signature #### Signature
```python ```python
def compile(filename: str = None, output: str = None, loglevel=logging.INFO) def compile(filename: str = None, output: str = None, loglevel=logging.WARNING)
``` ```
#### Parameters #### Parameters
* `filename` - Path to the Python source file (default: calling file) * `filename` - Path to the Python source file (default: calling file)
* `output` - Path for the output object file (default: same name with `.o` extension) * `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 #### Usage
@ -107,17 +90,6 @@ This function generates a `.o` file containing BPF bytecode that can be:
* Verified with the BPF verifier * Verified with the BPF verifier
* Distributed as a compiled binary * 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 ### BPF Class
The `BPF` class provides a high-level interface to compile, load, and attach BPF programs. 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 ```python
class BPF: class BPF:
def __init__(self, filename: str = None, loglevel=logging.INFO) def __init__(self, filename: str = None, loglevel=logging.WARNING)
def load(self) def load(self)
def attach_all(self) def attach_all(self)
def load_and_attach(self) def load_and_attach(self)
@ -135,7 +107,7 @@ class BPF:
#### Parameters #### Parameters
* `filename` - Path to Python source file (default: calling file) * `filename` - Path to Python source file (default: calling file)
* `loglevel` - Logging level (default: `logging.INFO`) * `loglevel` - Logging level (default: `logging.WARNING`)
#### Methods #### Methods
@ -212,7 +184,7 @@ from ctypes import c_void_p, c_int64
@section("tracepoint/syscalls/sys_enter_execve") @section("tracepoint/syscalls/sys_enter_execve")
def trace_exec(ctx: c_void_p) -> c_int64: def trace_exec(ctx: c_void_p) -> c_int64:
print("Process started") print("Process started")
return c_int64(0) return 0
@bpf @bpf
@bpfglobal @bpfglobal
@ -224,13 +196,13 @@ if __name__ == "__main__":
b = BPF() b = BPF()
b.load_and_attach() b.load_and_attach()
trace_pipe() trace_pipe()
# Method 2: Step-by-step # Method 2: Step-by-step
# b = BPF() # b = BPF()
# b.load() # b.load()
# b.attach_all() # b.attach_all()
# trace_pipe() # trace_pipe()
# Method 3: Manual compilation # Method 3: Manual compilation
# from pythonbpf import compile # from pythonbpf import compile
# compile(filename="my_program.py", output="my_program.o") # 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 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 ### Kernel Loading
The compiled object is loaded using `pylibbpf`: The compiled object is loaded using `pylibbpf`:
@ -301,13 +268,6 @@ obj = BpfObject(path="program.o")
obj.load() obj.load()
``` ```
The kernel verifier checks:
* Memory access patterns
* Pointer usage
* Loop bounds
* Instruction count
* Helper function calls
## Debugging Compilation ## Debugging Compilation
### Logging ### Logging
@ -364,24 +324,11 @@ bpftool map dump id <ID>
If the kernel verifier rejects your program: If the kernel verifier rejects your program:
1. Check `dmesg` for detailed error messages: * Check `dmesg` for detailed error messages:
```bash ```bash
sudo dmesg | tail -50 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 ## Compilation Options
### Optimization Levels ### Optimization Levels
@ -395,20 +342,11 @@ While PythonBPF doesn't expose optimization flags directly, you can:
2. Modify the compilation pipeline in your code 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 ### Debug Information
PythonBPF automatically generates debug information (DWARF) for: PythonBPF automatically generates debug information (DWARF) for:
* Function names * Function names
* Line numbers
* Variable names * Variable names
* Type information * Type information
@ -461,41 +399,6 @@ BPF objects are generally compatible across kernel versions, but:
* Helper functions may not be available on older kernels * Helper functions may not be available on older kernels
* BTF (BPF Type Format) requirements vary * 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 ## Troubleshooting
### Compilation Fails ### Compilation Fails