# How to Dynamically Attach bpftime to a Running Process: Complete Guide

> Dynamically attach bpftime to a running process using the bpftime attach PID command and Frida. Instrument your target without restarting for seamless eBPF integration.

- Repository: [eunomia-bpf/bpftime](https://github.com/eunomia-bpf/bpftime)
- Tags: how-to-guide
- Published: 2026-03-01

---

**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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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

- `bpftime` tools 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:

```bash
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:

```bash
./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:

```bash
sudo bpftime attach $pid

```

The output confirms successful injection:

```text
Inject: "/root/.bpftime/libbpftime-agent.so"
Successfully injected. ID: 1

```

Optional: Enable syscall tracing during attachment by adding the `-s` flag:

```bash
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:

```bash

# 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.

```cpp
#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 &regs){ /* 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:

```bash
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 load` so attached processes can immediately access them.
- Detach agents globally using `bpftime detach` when instrumentation is complete.
- The underlying implementation spans [`tools/README.md`](https://github.com/eunomia-bpf/bpftime/blob/main/tools/README.md), [`frida_uprobe_attach_impl.hpp`](https://github.com/eunomia-bpf/bpftime/blob/main/frida_uprobe_attach_impl.hpp), and [`base_attach_impl.hpp`](https://github.com/eunomia-bpf/bpftime/blob/main/base_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`](https://github.com/eunomia-bpf/bpftime/blob/main/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.