Understanding the bpftime Architecture: Core Components and Design
The bpftime architecture consists of six primary modules—a modular VM for bytecode execution, a runtime for object management and shared memory, an attach system for event hooking, a userspace verifier for safety analysis, an LD_PRELOAD loader for process injection, and an optional daemon for kernel integration—that together enable high-performance userspace eBPF execution.
The bpftime project, hosted at eunomia-bpf/bpftime, provides a complete userspace eBPF runtime designed for attaching to arbitrary processes without kernel cooperation. Understanding the bpftime architecture is essential for developers extending the platform or optimizing eBPF program performance in userspace environments.
Core Components of the bpftime Architecture
The bpftime architecture is organized into distinct layers, each responsible for a specific aspect of the eBPF lifecycle. These components interact through well-defined APIs to provide a seamless execution environment.
1. VM (Virtual Machine)
The VM component executes eBPF bytecode and supports multiple backend implementations for different performance and compatibility requirements. Located in the vm/ directory, it abstracts the execution engine from the rest of the system.
Key implementations include:
- LLVM-based JIT/AOT: Uses
llvmbpffor native code generation - ubpf: Provides both interpreter and JIT compilation modes
- Standalone library: For embedded scenarios requiring minimal dependencies
The VM interface is defined in vm/vm-core/include/ebpf-vm.h, which serves as the primary contract between execution engines and the runtime.
2. Runtime
The Runtime manages eBPF objects including maps, helpers, and user functions (ufuncs). Implemented primarily in the runtime/ directory, it provides the shared-memory infrastructure that enables zero-copy map access between processes.
Core responsibilities include:
- Object lifecycle management for programs and maps
- Safety checks and resource limits
- Shared memory allocation for
bpftimemaps accessible across process boundaries
The public API is exposed through runtime/include/bpftime.hpp, while internal object tracking occurs in runtime/src/handler/handler_manager.hpp.
3. Attach Events
The Attach component provides the plugin system for hooking eBPF programs to event sources. Located in attach/, it abstracts the mechanism by which execution is triggered.
Supported attachment types include:
- Uprobes: User-space function interception
- Syscall tracepoints: System call monitoring
- XDP: Network packet processing (userspace implementation)
- GPU kernels: Accelerated computing event hooks
The reference implementation for simple uprobes resides in attach/simple_attach_impl/simple_attach_impl.cpp.
4. Verifier
The Verifier performs static safety analysis on eBPF programs before loading. Found in bpftime-verifier/, it ensures programs cannot crash the runtime or access unauthorized memory.
Key characteristics:
- Uses the PREVAIL userspace verifier by default
- Can delegate verification to the Linux kernel verifier when available
- Validates memory access patterns and instruction sequences
The entry point is bpftime-verifier/src/bpftime-verifier.cpp.
5. Loader and Agent
The Loader injects the bpftime runtime into target processes without requiring application recompilation. It consists of:
- LD_PRELOAD agent: A shared library (
libbpftime-agent.so) that initializes the runtime when injected viaLD_PRELOAD - CLI tools: The
bpftimecommand-line interface for loading objects and attaching to processes
Implementation resides in runtime/syscall-server/loader.cpp.
6. Daemon
The optional Daemon enables interoperability between userspace bpftime programs and the kernel eBPF subsystem. Located in daemon/, it allows hybrid deployments where some programs run in kernel space and others in userspace.
How the bpftime Architecture Works
The components interact in a defined pipeline to execute eBPF programs:
- Compilation: Developers compile eBPF programs using standard
clangandlibbpftoolchains. - Verification: The verifier validates bytecode safety using PREVAIL or kernel verification.
- Loading: The loader injects the runtime via
LD_PRELOADor explicit CLI commands. - Execution: The VM executes bytecode, utilizing runtime-managed maps and helpers.
- Attachment: The attach system rewrites target binaries or intercepts syscalls to trigger program execution on events.
- Inter-process sharing: Maps reside in shared memory, enabling zero-copy data exchange between processes.
Implementation Details and Key Files
Understanding the source layout is crucial for extending the architecture:
vm/vm-core/include/ebpf-vm.h: Defines the VM interface used by all execution backends.runtime/include/bpftime.hpp: Public API for map creation, program loading, and runtime interaction.runtime/src/handler/handler_manager.hpp: Central registry managing eBPF objects in shared memory.attach/simple_attach_impl/simple_attach_impl.cpp: Reference uprobe attachment implementation.bpftime-verifier/src/bpftime-verifier.cpp: Entry point for the PREVAIL safety verifier.runtime/syscall-server/loader.cpp: Implements theLD_PRELOADinjection mechanism.daemon/: Contains kernel interoperability daemon code.
Practical Examples
Loading and Running a Uprobe Program
Compile and execute an eBPF program targeting malloc calls:
# Build the example
make -C example/malloc
# Add bpftime to PATH
export PATH=$PATH:~/.bpftime/
# Load the eBPF object
bpftime load ./example/malloc/malloc
# Start the target program
bpftime start ./example/malloc/victim
Attaching to a Running Process
Inject bpftime into an already executing process:
# Start target in background and capture PID
./example/malloc/victim & echo $! # Output: 101771
# Attach loaded eBPF program to PID
sudo bpftime attach 101771
Using the LD_PRELOAD Agent
Directly inject the runtime without CLI tools:
# Set the agent library path
export LD_PRELOAD=$HOME/.bpftime/libbpftime-agent.so
# Execute any binary; runtime initializes automatically
./my_app
Summary
- The bpftime architecture comprises six modular components: VM, Runtime, Attach, Verifier, Loader/Agent, and Daemon.
- The VM supports multiple backends (LLVM, ubpf) for flexible bytecode execution.
- The Runtime manages shared-memory maps and eBPF objects, enabling inter-process communication.
- The Attach system provides pluggable event sources from uprobes to GPU kernels.
- The Verifier ensures safety using PREVAIL or kernel verification before execution.
- The Loader uses
LD_PRELOADfor non-invasive process injection, while the Daemon enables kernel interoperability.
Frequently Asked Questions
What is the bpftime architecture designed for?
The bpftime architecture is designed to execute eBPF programs entirely in userspace without kernel dependencies. It enables attaching eBPF programs to arbitrary user-space functions, system calls, and even GPU kernels while providing kernel-compatible map semantics and verification.
How does bpftime differ from kernel eBPF?
Unlike kernel eBPF, which requires root privileges and kernel version compatibility, bpftime runs in userspace using LD_PRELOAD injection. It uses shared memory for maps instead of kernel objects, supports attaching to already-running processes, and can operate without kernel eBPF support entirely.
What verifier does bpftime use for safety checks?
Bpftime uses the PREVAIL userspace verifier by default, located in bpftime-verifier/src/bpftime-verifier.cpp. It can also delegate verification to the Linux kernel verifier when available, providing flexibility in safety validation approaches.
Can bpftime attach to processes that are already running?
Yes, bpftime supports attaching to existing processes through the bpftime attach <PID> command. This uses the agent infrastructure in runtime/syscall-server/loader.cpp to inject the runtime into a running process without requiring restart or recompilation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →