为什么 eBPF 堆栈跟踪中的指令指针包含两次具有相同 IP 的 eBPF 程序,以及一个奇怪的不相关 IP?

为什么 eBPF 堆栈跟踪中的指令指针包含两次具有相同 IP 的 eBPF 程序,以及一个奇怪的不相关 IP?

当在 eBPF 程序中获取内核堆栈跟踪时,我得到了重复且看似奇怪的条目:有人可以解释一下吗?

让我们从相关的 eBPF 程序片段开始;首先,我声明了一个堆栈跟踪图,如下所示:

struct {
    __uint(type, BPF_MAP_TYPE_STACK_TRACE);
    __type(key, u32);
    __type(value, stack);
    __uint(max_entries, 1 << 14);
} stacks SEC(".maps");

在 eBPF 程序(稍后附加到cap_capable)中,我按如下方式存储堆栈跟踪,然后将堆栈跟踪 ID 发送到用户空间:

kstackid = bpf_get_stackid(ctx, &stacks, 0);

用户空间方面在 Go 中,使用 Cilium 非常有用ebpf Go 模块。为了读取特定堆栈回溯的指令指针,我执行以下操作:

ips := make([]uint64, MaxStackDepth)
if err := objs.Stacks.Lookup(event.Kstackid, ips); err != nil {
    slog.Error("looking up kernel stack trace", "error", err)
    continue
}
l := len(ips)
for idx, ip := range ips {
    if ip == 0 {
        l = idx
        break
    }
}
ev := Event{
    bpfCapevent: event,
    KernelStack: ips[:l],
}

现在,当我使用来自的数据解析指令指针时,/proc/kallsyms最终会得到一个如下所示的堆栈,还会显示 IP:

bpf_prog_47f71ae01d77a0b5_fentry_cap_capable ffffffffc00860ed
bpf_prog_47f71ae01d77a0b5_fentry_cap_capable ffffffffc00860ed
udp_tunnel_nic_init_module ffffffffc0e2004f
cap_capable ffffffff9ea9b1a5
  1. 为什么会有fentry 的 IP 地址cap_capable?它们都是相同的返回地址,那么这里发生了什么?
  2. cap_capable我的 eBPF 程序之间的中间函数是什么,udp_tunnel_nic_init_module看起来像是误解?会不会和蹦床有关……?

相关内容