如何使用 ebpf 获取 goroutine id

我使用 cilium ebpf pakage 编写了一个 ebpf 程序来获取 goroutine id。但失败了。我的 uprobe.c 是这样的:我认为关键问题是 golang struct g trans to goroutine.h 是错误的。谁能帮忙?


uprobe.c


SEC("uprobe/runtime.newproc1")

int uprobe_runtime_newproc1(struct pt_regs *ctx) {

    u32 key     = 2;

    u64 initval = 1, *valp;


    valp = bpf_map_lookup_elem(&uprobe_map, &key);

    if (!valp) {

        bpf_map_update_elem(&uprobe_map, &key, &initval, BPF_ANY);

        return 0;

    }

    __sync_fetch_and_add(valp, 1);


    struct g* goroutine_struct = (void *)PT_REGS_PARM4(ctx);


    // retrieve output parameter

    s64 goid = 0;

    bpf_probe_read(&goid, sizeof(goid), &goroutine_struct->goid);


    bpf_printk("bpf_printk bpf_probe_read goroutine_struct->goid: %lld", goid);



    struct g gs;

    bpf_probe_read(&gs, sizeof(gs), (void *)PT_REGS_PARM4(ctx));

    bpf_printk("bpf_printk bpf_probe_read goroutine_struct.goid: %lld", gs.goid);


    // test

    void* ptr = (void *)PT_REGS_PARM4(ctx);

    s64 goid2 = 0;

    bpf_probe_read(&goid2, sizeof(goid2), (void *)(ptr+152));

    bpf_printk("bpf_printk bpf_probe_read goid2: %lld", goid2);


    return 0;

}

当我运行我的程序时,cat /sys/kernel/debug/tracing/trace_pipe 输出像这样,得到错误的 go id:


<...>-1336127 [000] d... 20113210.986990: bpf_trace_printk: bpf_printk bpf_probe_read goroutine_struct->goid: 4938558469562467144

<...>-1336127 [000] d... 20113210.986998: bpf_trace_printk: bpf_printk bpf_probe_read goroutine_struct.goid: 4938558469562467144

<...>-1336127 [000] d... 20113210.986998: bpf_trace_printk: bpf_printk bpf_probe_read goid2: 4938558469562467144

Blockquote


拉丁的传说
浏览 60回答 1
1回答

慕容森

我找到了一个解决方案:我的 golang 版本是 1.17.2,amd64。amd64 架构使用以下 9 个寄存器序列作为整数参数和结果:RAX、RBX、RCX、RDI、RSI、R8、R9、R10、R11runtime.newproc1 在 go 1.17.2 中有 5 个参数。callergp *g 是第 4 个。当我 gdb 我的用户空间程序时,它使用 rdi 寄存器来保存 callergp *g 的 ptr addr。所以使用 PT_REGS_PARM1 是正确的方法。因为 (#define PT_REGS_PARM1(x) ((x)->rdi))毕竟,这样的代码:&nbsp; &nbsp; SEC("uprobe/runtime.newproc1")&nbsp; &nbsp; int uprobe_runtime_newproc1(struct pt_regs *ctx) {&nbsp; &nbsp; &nbsp; &nbsp; u32 key&nbsp; &nbsp; &nbsp;= 2;&nbsp; &nbsp; &nbsp; &nbsp; u64 initval = 1, *valp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; valp = bpf_map_lookup_elem(&uprobe_map, &key);&nbsp; &nbsp; &nbsp; &nbsp; if (!valp) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bpf_map_update_elem(&uprobe_map, &key, &initval, BPF_ANY);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 0;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; __sync_fetch_and_add(valp, 1);&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // retrieve output parameter&nbsp; &nbsp; &nbsp; &nbsp; struct g gs;&nbsp; &nbsp; &nbsp; &nbsp; bpf_probe_read(&gs, sizeof(gs), (void *)PT_REGS_PARM1(ctx));&nbsp; &nbsp; &nbsp; &nbsp; bpf_printk("uprobe_runtime_newproc1 bpf_printk bpf_probe_read goroutine_struct.goid: %lld", gs.goid);&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return 0;&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP