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:
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user