You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在eBPF的入口与返回探针中获取被调用函数名称

解决eBPF返回探针关联被调用函数的通用方法

核心问题是函数退出后,PT_REGS_IP(ctx)返回的是调用者的指令地址,无法直接拿到被追踪函数的信息。以下是无需硬编码的通用解决方案:

方法原理

利用哈希表存储入口事件的上下文(进程ID+返回地址作为唯一键),返回探针通过相同的键查找对应的函数信息,实现进出事件的关联。

1. eBPF核心代码(C部分)

#include <uapi/linux/ptrace.h>

// 存储函数信息的结构体
struct func_info {
    char name[64];
    u64 addr;
};

// 哈希表:键为进程ID+返回地址,值为函数信息
BPF_HASH(func_map, struct { u32 pid; u64 ret_addr; }, struct func_info);

// 通用入口探针:记录函数地址、名称及关联键
int kprobe__enter_func(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    // 获取返回地址(x86_64下为当前指令地址,其他架构需适配)
    u64 ret_addr = PT_REGS_RIP(ctx);
    u64 func_addr = PT_REGS_IP(ctx);

    struct func_info info = {};
    info.addr = func_addr;
    // 通过地址解析函数名称,无需硬编码
    bpf_get_sym(func_addr, info.name, sizeof(info.name));

    struct { u32 pid; u64 ret_addr; } key = {pid, ret_addr};
    func_map.update(&key, &info);

    bpf_trace_printk("Enter: %s [0x%llx]\n", info.name, info.addr);
    return 0;
}

// 通用返回探针:通过键查找函数信息,关联退出事件
int kretprobe__exit_func(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    u64 ret_addr = PT_REGS_IP(ctx); // 与入口时记录的返回地址一致

    struct { u32 pid; u64 ret_addr; } key = {pid, ret_addr};
    struct func_info *info = func_map.lookup(&key);

    if (info) {
        bpf_trace_printk("Exit: %s [0x%llx]\n", info->name, info->addr);
        func_map.delete(&key); // 清理条目,避免内存泄漏
    }
    return 0;
}

2. Python层挂载探针(动态支持任意函数)

from bcc import BPF

# 可自定义要跟踪的函数列表,无需硬编码
TARGET_FUNCTIONS = ["my_func_1", "my_func_2", "my_func_3"]

# 加载eBPF程序
bpf = BPF(text=open("trace_funcs.c").read())

# 为每个目标函数挂载入口和返回探针
for func in TARGET_FUNCTIONS:
    bpf.attach_kprobe(event=func, fn_name="kprobe__enter_func")
    bpf.attach_kretprobe(event=func, fn_name="kretprobe__exit_func")

# 持续打印跟踪日志
bpf.trace_print()

关键注意事项

  • 架构适配:不同CPU架构的返回地址获取方式不同,比如ARM架构需用PT_REGS_LR(ctx)替代PT_REGS_RIP(ctx),可通过宏定义#ifdef __x86_64__做条件编译。
  • 符号解析:bpf_get_sym()依赖内核开启CONFIG_KALLSYMS和CONFIG_DEBUG_INFO_BTF(或传统符号表),确保内核支持地址到符号的解析。
  • 内存管理:返回探针处理完成后必须删除哈希表条目,避免长时间运行导致内存泄漏。

内容的提问来源于stack exchange,提问作者TreeWater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 21:13:13