为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 ebpf 获取 goroutine id

如何使用 ebpf 获取 goroutine id

Go
拉丁的传说 2023-03-15 13:49:26
我使用 cilium ebpf pakage 编写了一个 ebpf 程序来获取 goroutine id。但失败了。我的 uprobe.c 是这样的:我认为关键问题是 golang struct g trans to goroutine.h 是错误的。谁能帮忙?uprobe.cSEC("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: 4938558469562467144Blockquote
查看完整描述

1 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

我找到了一个解决方案:

  1. 我的 golang 版本是 1.17.2,amd64。amd64 架构使用以下 9 个寄存器序列作为整数参数和结果:RAX、RBX、RCX、RDI、RSI、R8、R9、R10、R11

  2. runtime.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))

  3. 毕竟,这样的代码:

    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);

    

        // retrieve output parameter

        struct g gs;

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

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

    

        return 0;

    }


查看完整回答
反对 回复 2023-03-15
  • 1 回答
  • 0 关注
  • 55 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信