Post content
今天晨间剧是“原来这就是 CO-RE” ,之前没有需求所以但丁问我的时候一问三不知。 总之大家在写 bpf 的时候用使用内核结构体。比如我有个 macro #define OFF_XFRM_MIB offsetof(struct net, mib) 但是在 5.x 和 6.x 内核下这个 offset 是不同的。 bcc / bpftrace 的解决办法是现场编译,但是这样需要在目标机器上安装 clang,这让我这种静态链接爱好者感到伤心。 另一个解法就是 CO-RE 了。总之你在 vmlinux.h 里把 struct net 的地方加上 __attribute__((preserve_access_index)) ,bpf loader 就能自动调节 bpf 字节码。(或者用 CORE_READ 系列 macro) 不要和 verifier 的字段调整混淆了。verifier 会调整字段,比如 tc-bpf 的 skb 参数,会把 skb->data_end 调整到 cb[5] ,但是 CO-RE relocation 是用户态的调整。首先在发布环境,clang 会编译出 bpf object,然后 go 把 bpf 字节码一起编译进 ELF;然后在运行环境,进程会在内存里通过运行时内核 btf 来调整 bpf opcode,然后再加载到内核。所以一个是用户态调整,一个是内核态调整。 其实概念不难,基本是工程问题。同时也感慨内核暴露的 debug info 真是多,我以前总以为要先下载 dbgsym,现在还下载个屁,直接 kallsyms + btf 就等于符号表 + 函数入口的 .debug_info ,还保证有 frame pointer,调试用户态 ELF 能有这种条件保证做梦都要笑醒。