How to Dynamically Attach bpftime to a Running Process: Complete Guide
Use the bpftime attach <PID> command to inject the userspace eBPF runtime into an existing process via Frida, enabling dynamic instrumentation without restarting the target.
The eunomia-bpf/bpftime repository provides a userspace eBPF runtime that allows you to dynamically attach bpftime to a running process without requiring a restart or code modification. This capability leverages Frida's dynamic instrumentation framework to inject the libbpftime-agent.so shared object into the target process's address space, establishing a shared-memory connection to the eBPF runtime.
Understanding the Dynamic Attachment Architecture
The dynamic attachment system in bpftime operates through three distinct layers that handle the transition from CLI command to active instrumentation.
CLI Front-End Layer
The command-line interface parses the bpftime attach <PID> instruction and forwards the request to the injection subsystem. This layer handles PID validation to ensure the target process exists and is accessible to the current user, as documented in tools/README.md.
Frida Injection Layer
The Frida-based injector uses the Frida library to perform a remote dlopen of the agent shared object (libbpftime-agent.so) inside the target process. This implementation resides in attach/frida_uprobe_attach_impl/include/frida_uprobe_attach_impl.hpp, which manages the low-level process injection without requiring target cooperation.
Agent Runtime Layer
Once injected, the agent registers the Frida attach implementation (frida_attach_impl) with the global handler manager. This class, defined in attach/base_attach_impl/base_attach_impl.hpp, creates uprobe and uretprobe entries, stores them in the shared-memory manager (runtime/include/bpftime_shm.hpp), and executes eBPF programs when probed functions fire.
Step-by-Step Guide to Attach bpftime to a Running Process
Follow this workflow to dynamically instrument an existing process using the bpftime CLI.
Prerequisites
bpftimetools installed and available in your PATH- Target process running with appropriate permissions
- Sudo access for cross-user attachment
Step 1: Load eBPF Programs into Shared Memory
Before attaching to a process, load the eBPF programs that will instrument the target:
bpftime load ./example/malloc/malloc
This registers the eBPF program with the shared-memory manager, making it available to any process you subsequently attach.
Step 2: Identify the Target Process
Locate the PID of the running process you want to instrument:
./example/malloc/victim &
pid=$!
echo "Target PID: $pid"
Step 3: Execute Dynamic Attachment
Inject the bpftime agent into the running process using the attach command:
sudo bpftime attach $pid
The output confirms successful injection:
Inject: "/root/.bpftime/libbpftime-agent.so"
Successfully injected. ID: 1
Optional: Enable syscall tracing during attachment by adding the -s flag:
sudo bpftime attach -s $pid
Step 4: Verify Attachment
Once attached, the eBPF program will begin collecting data. Verify the instrumentation is active by checking the program output:
# The agent feeds map data to the shared memory
# Sample output showing malloc call counts:
pid=247299 malloc calls: 10
pid=247322 malloc calls: 10
Programmatic Attachment Using the C++ API
For custom controllers or embedded scenarios, you can invoke the attachment mechanism programmatically using the bpftime runtime API. This approach uses the same underlying classes as the CLI.
#include "runtime/include/bpftime.hpp"
#include "runtime/include/bpftime_shm.hpp"
#include "attach/base_attach_impl/base_attach_impl.hpp"
#include "attach/frida_uprobe_attach_impl/include/frida_uprobe_attach_impl.hpp"
int main()
{
// 1. Connect to the shared-memory manager
auto shm = bpftime::shm::open_or_create();
// 2. Load an eBPF program
auto prog_fd = bpftime::load_elf("./example/malloc/malloc", shm);
// 3. Initialize Frida attach implementation
pid_t target = 101771; // Replace with actual target PID
bpftime::attach::frida_attach_impl frida_impl;
// Register with global handler manager (automatic in constructor)
bpftime::handler_manager::instance().register_attach_impl(&frida_impl);
// 4. Create a uprobe on target function
void *malloc_addr = /* resolve symbol address */;
int attach_id = frida_impl.create_uprobe_at(
malloc_addr,
[](const pt_regs ®s){ /* optional callback */ }
);
// eBPF programs now execute when malloc is called in the target
return 0;
}
Note: The programmatic API is rarely required for standard use cases; the CLI bpftime attach command performs these steps internally.
Managing Attached Agents
After dynamic attachment, you may need to detach agents or modify tracing behavior.
Detaching from Processes
To remove the bpftime agent from all attached processes, use the detach command:
bpftime detach
This sends SIGUSR1 to every process that received an agent, causing the injected code to clean up and unload.
Summary
Dynamic attachment in bpftime enables runtime instrumentation of existing processes without restarts or code changes. Key takeaways include:
- Use
bpftime attach <PID>to inject the agent into running processes via Frida. - The injection loads
libbpftime-agent.so, which registers the Frida attach implementation and connects to the shared-memory eBPF runtime. - Pre-load eBPF programs using
bpftime loadso attached processes can immediately access them. - Detach agents globally using
bpftime detachwhen instrumentation is complete. - The underlying implementation spans
tools/README.md,frida_uprobe_attach_impl.hpp, andbase_attach_impl.hpp.
Frequently Asked Questions
Does bpftime require restarting the target process?
No. The dynamic attachment mechanism uses Frida to remotely inject the libbpftime-agent.so shared object into the target process's address space. This allows you to attach bpftime to long-running services or critical infrastructure without downtime or process restarts.
What permissions are needed to attach to a process?
You must have permission to send signals and access the target process's memory. Typically, this means running as the same user who owns the target process, or using sudo for cross-user attachment. The CLI validates the PID and ownership before attempting injection.
How does bpftime communicate with the attached process?
After injection, the agent establishes a connection to the bpftime shared-memory region (bpftime_shm). This shared-memory manager, defined in runtime/include/bpftime_shm.hpp, stores eBPF programs and maps, allowing the attached process to execute eBPF logic and share data with other instrumented processes.
Can I attach to multiple processes simultaneously?
Yes. You can run bpftime attach <PID> multiple times with different process IDs. Each injection loads an independent agent instance that connects to the same shared-memory runtime. To detach all agents at once, use bpftime detach, which signals every injected process to clean up.
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 →