
CO-RECompile Once – Run Everywhere的自动定位核心是编译时记录类型 / 字段元数据、加载时用目标内核 BTF 做类型匹配与偏移重定位让同一份 eBPF 程序自动适配不同内核版本的结构体布局。不同内核版本中struct task_struct、struct sk_buff等内核结构体的字段偏移、大小、存在性会变化硬编码偏移会导致程序崩溃。CO-RE 解决编译不绑定具体偏移加载时自动计算目标内核的真实偏移。BTFBPF Type Format内核侧/sys/kernel/btf/vmlinux包含完整内核类型、结构体、字段、偏移的元数据。程序侧Clang 为 eBPF 程序生成.BTF.BTF.ext段记录程序用到的类型与字段引用。BTF 给运行时看的「二进制结构地图 精准偏移」BTF 内核的 “调试说明书 结构地图”它把内核里所有结构体struct联合体union枚举enum类型定义typedef函数原型字段偏移、大小、位域全部以二进制格式存在内核里让 eBPF 程序运行时能看懂内核结构。它不是文本是内核导出的二进制数据/sys/kernel/btf/vmlinux这就是整个内核的完整类型信息。你可以用工具查看bpftool btf dump file /sys/kernel/btf/vmlinux format c会输出类似struct task_struct { pid_t pid; char comm[16]; // ... 所有字段 偏移 };CO-RE 之所以能跨内核完全靠 BTF编译时只记录 “我要访问 task-pid”加载时BTF 告诉程序 pid 在内核里的真实偏移没有 BTF → CO-RE 彻底不能用。以前写 eBPF 必须装内核头文件适配版本为每个内核编译有了 BTF不需要内核头文件一次编译到处运行BTF 里对 eBPF 最重要的 4 类信息结构体名字字段名字字段偏移offset字段大小sizeCO-RE 就是读取这 4 个信息完成自动定位。Clang 编译器编译时用__builtin_preserve_access_index()标记需要重定位的结构体访问如task-pid。生成CO-RE 重定位记录存入.BTF.ext外层结构体 BTF ID字段名 / 路径如pid重定位类型偏移、大小、存在性等。不生成硬编码偏移只保留 “符号化引用”。libbpf 加载器加载时读取目标内核的 BTFvmlinux。对每条重定位记录做类型匹配 字段定位匹配程序侧结构体如task_struct与内核侧同名结构体。按字段名 / 类型找到目标字段。计算该字段在目标内核中的真实偏移。动态修改 eBPF 指令对LDX/STX指令替换偏移立即数为真实偏移。对ALU指令替换立即数为字段大小、是否存在等信息。/sys/kernel/btf/vmlinux这是整个 eBPF CO-RE 世界里最重要的一个文件全称内核 BTF 类型数据文件一句话这是当前运行内核的「完整内存结构地图」二进制格式。它包含内核里所有结构体、联合体、枚举的定义每个字段的真实偏移、大小、位域函数原型、类型别名100% 对应当前内核内存的真实布局内核自动暴露的sysfs 虚拟文件不是磁盘文件重启不丢失只要内核开启 BTF就一定存在内核编译时打开配置CONFIG_DEBUG_INFO_BTFy编译过程会从 DWARF 调试信息提取类型转换成紧凑的 BTF 格式打包进内核镜像启动后暴露成/sys/kernel/btf/vmlinux支持情况内核 ≥ 5.8默认开启 ✅内核 5.0~5.7部分支持内核 5.0默认没有 ❌CentOS 7、Ubuntu 18自动定位完整流程编译 → 加载1. 编译阶段Clang// eBPF 代码 struct task_struct *task (void *)bpf_get_current_task(); pid_t pid task-pid; // 被 __builtin_preserve_access_index() 包裹Clang 识别task-pid为需要重定位的访问。生成重定位项struct task_struct→ 字段pid→ 类型BPF_FIELD_BYTE_OFFSET。输出 ELF 含.BTF程序类型、.BTF.ext重定位记录。2. 加载阶段libbpf读取内核 BTF获取目标内核task_struct完整布局与pid偏移如 0x40。重定位匹配程序侧找struct task_struct的pid字段。内核侧用 BTF 查该字段真实偏移。指令修补原指令LDX BPF_DW, r0, [r10]偏移 0 是占位。修补后LDX BPF_DW, r0, [r10x40]替换为真实偏移。加载验证内核验证器接受修补后的指令程序正常运行。关键重定位类型自动定位能力类型作用示例BPF_FIELD_BYTE_OFFSET自动计算字段偏移task-pid偏移BPF_FIELD_EXISTS检测字段是否存在bpf_core_field_exists(task-exit_code)BPF_FIELD_BYTE_SIZE自动适配字段大小sizeof(task-comm)BPF_FIELD_SIGNED处理符号位差异有符号 / 无符号字段适配位域重定位自动计算位域偏移 / 掩码位域字段访问自动定位的核心机制类型安全匹配按结构体名 字段名 类型三重匹配避免误匹配。支持___后缀忽略如task_struct___local匹配task_struct。字段路径重定位支持嵌套访问如task-files-fdt-fd[0]自动计算整条路径的偏移总和。兼容性处理字段缺失用bpf_core_field_exists()做分支自动返回 0/1。类型变化自动适配unsigned long等在不同架构的位宽。核心必用场景离开 CO-RE 基本无法开发这些场景必须依赖 CO-RE 自动定位否则代码只能在单个内核版本运行完全不具备通用性。直接访问内核核心结构体最主流只要代码里读写内核原生结构体比如struct task_struct进程信息PID、进程名、栈、父进程struct sk_buff网络包五元组、端口、载荷struct file/struct inode文件系统struct cred权限、UID/GIDstruct bpf_mapeBPF map 内部结构CO-RE 作用自动适配不同内核里字段偏移、大小、存在性的变化不用手动维护偏移表。跨内核版本分发的生产级 eBPF 工具比如你要开发一个可在 CentOS 7/8/9、Ubuntu 18.04/20.04/22.04、Amazon Linux、Kylin 等任意发行版运行的观测 / 安全工具。CO-RE 作用编译一个二进制文件全平台运行不需要为每个内核版本单独编译。云原生 / Kubernetes 环境观测K8s 节点内核版本五花八门容器观测进程、网络、文件服务网格可观测性云原生安全运行时防护CO-RE 作用一套 DaemonSet 镜像全集群运行无内核版本依赖。CO-RE 自动定位的局限性依赖内核开启 BTF最硬性限制CO-RE 自动定位100% 依赖目标内核提供 BTF 信息/sys/kernel/btf/vmlinux。内核 5.8默认不开启 BTFCentOS 7、Ubuntu 18.04 等老旧系统厂商裁剪内核很多嵌入式、定制内核直接删掉 BTF无 BTF → CO-RE 完全失效无法做任何自动定位解决方案只能手动打包 BTF 信息vmlinux.h或升级内核但这破坏了 “一次编译” 的优势。只能定位 “字段偏移 / 存在性”不能修复逻辑变更CO-RE只会改偏移不会改代码逻辑。如果内核字段语义变了、功能删了、逻辑重构了CO-RE 无能为力。例子内核把task-pid改成task-thread_pid内核把某个统计字段含义完全改变内核把某个函数 / 结构体重构CO-RE 能找到字段位置但无法自动适配业务逻辑变化你必须自己写兼容代码。不支持 “结构体改名 / 完全删除” 的自动兼容如果内核把struct A重命名为struct B直接删掉整个结构体用全新机制替代旧结构体CO-RE无法自动映射只能靠开发者手动处理。只支持 “直接字段访问”不支持复杂表达式自动重定位CO-RE 只能处理a-b-c但无法处理指针运算数组动态索引宏展开后的复杂计算内联函数里的隐式结构体访问这些必须手动改写成 CO-RE 可识别的格式。嵌套结构体过深时重定位容易失败例如task-files-fdt-fd[0]只要中间任意一层结构体改名字段删除类型变化整个路径重定位全部失败且 libbpf 不会自动降级。位域bitfield支持弱、容易出错内核很多字段是 bitfieldint flags : 12;CO-RE 能定位但不同内核位域布局可能变化跨架构x86 ↔ arm64位域兼容性差调试极困难bitfield 是 CO-RE 重定位故障率最高的地方。无法处理 union 成员的语义变化union 在不同内核里成员顺序变化成员类型变化复用方式变化CO-RE 只能定位偏移无法理解 union 的实际含义。内核模块的结构体无法用 CO-RECO-RE只支持 vmlinux 内核主程序的结构体。不支持第三方内核模块自己编写的内核模块动态加载的驱动结构体因为这些没有标准 BTF 信息。Clang 版本必须足够高CO-RE 重定位依赖Clang 10libbpf 0.5低版本编译器无法生成重定位信息生成的 BTF 不完整部分重定位类型不支持开发环境受限。无法跨架构自动适配x86 → arm64CO-RE 可以跨内核版本跨发行版但不能跨架构编译一次运行。x86 编译的 eBPF 代码不能在 ARM 运行必须按架构分别编译。重定位失败时调试非常困难CO-RE 是加载时静默重写指令问题包括失败不打印明确原因不知道是哪个字段找不到不知道是类型不匹配还是字段缺失生产环境排查 CO-RE 问题效率极低。无法自动处理 “内核补丁带来的非标结构”很多厂商华为、阿里、腾讯云厂商AWS、Azure会给内核打非标补丁修改结构体布局。CO-RE 可能出现误匹配偏移错误类型不匹配无法 100% 保证兼容所有定制内核。总结CO-RE 自动定位的本质是用 BTF 做 “类型与布局的中间层”编译时记录符号引用、加载时动态解析真实偏移实现一次编译、跨内核版本自动适配。CO-RE 只能解决 “结构体布局变化” 的问题解决不了 “内核逻辑 / 功能 / 接口变化” 的问题它依赖 BTF且只能处理标准内核主程序的简单字段访问。CO-RE 自动定位能做什么自动算字段偏移自动判断字段是否存在自动适配大小、位域、符号跨内核版本运行CO-RE不能做什么局限性不能离开 BTF 运行不能修复逻辑 / 语义变更不能自动适配结构体改名 / 删除不能处理内核模块不能跨架构不能自动兼容非标定制内核复杂表达式、指针运算不支持