Go 插件在 macOS 27 加载失败:段数量与 DWARF 不一致
plugin.Open 报 chained fixups 段数量不符,可能是链接后追加 DWARF 段与 fixup 描述不一致。核对特定 macOS、架构及工具链,再重建插件与宿主。
Go 插件编译成功,plugin.Open 却在 macOS 27.0 ARM64 上失败,错误包含 chained fixups, seg_count does not match number of segments。若默认构建失败,而不带 DWARF 的插件能加载,应检查 Mach-O 段描述,而不是先把插件路径当成唯一原因。
Go 1.27.1 和 1.25.14 出现过这一具体表现:外部链接器先写入链式修正信息,Go 链接器随后合并调试信息、追加 __DWARF 段,记录的段数量却没有同步增加。macOS 27 的动态加载器拒绝这种不一致文件。现有明确范围是 macOS 27.0 ARM64,不能直接扩大到所有系统与架构。
使用含正式处理的工具链重建
Go 1.27.3 的正式链接实现已经包含针对插件的处理:需要合并 DWARF,且外部链接器支持相应选项时,传入 -Wl,-no_fixup_chains。应使用项目支持的维护工具链重新生成插件,再核对实际链接命令与加载结果。
插件和宿主还需要兼容的 Go 工具链、构建设置及共同依赖。只替换一个 .so 而保留另一版工具链生成的宿主,可能转而出现包版本不一致等其他加载错误。保留旧产物与构建参数,通过原发布流程配套重建,不手工修改 Mach-O 中的计数字节。
暂时去掉 DWARF 有明确代价
尚不能升级时,可在已批准的开发构建中评估下面的局部过渡:
go build -buildmode=plugin -ldflags=-w -o ./plugin-check.so ./plugin
包路径和输出文件是示例,应保留项目原来的目标与其他必要参数。-w 去掉 DWARF 调试信息,可能影响调试和故障定位;它不是无代价的长期默认值,也不表示插件代码或依赖已经兼容宿主。
另一个方向是给支持该参数的 Apple 外部链接器传 -no_fixup_chains,但参数应仅用于确认过的 Darwin 插件构建。不要把 Apple linker 参数原样塞给 Linux 或其他工具链。
验收应由原宿主加载新插件、查找并调用预期导出符号,而不只看构建退出码。xcrun dyld_info -fixups 可辅助检查文件结构,但静态检查成功也不能替代真实插件调用。如果仍报包版本、符号或签名问题,按新的完整错误分开处理,不继续用段数量故障解释一切。


