mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2026-02-07 13:40:59 +00:00
docs: Fix user-guide/compilation
This commit is contained in:
@ -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 <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
|
||||
|
||||
Reference in New Issue
Block a user