跳转至

Go 二进制构建元数据

inspect_go_binary / inspect-go-binary 用于确定选定的单个本地可执行文件或库中嵌入了哪个 Go 编译器版本、哪些模块、替换项以及构建设置。它只读取文件而不运行它,并且无需安装 Go、活动二进制目标、Hopper、Ghidra 或 IDA。

如果稳定读取完成,但描述符终结失败或收到取消操作,错误信息会将选定的路径、SHA-256 和字节长度保留为 file-snapshot-hash 部分观测结果。它不会声称已解码 Go 元数据。失败的清理会一直不完整,直到其确切所有者确认释放;取消操作会保留调用方的原因。

rea inspect-go-binary /absolute/path/to/application --json

CLI 会根据调用方的工作目录解析相对路径。MCP 要求提供绝对文件系统路径,并保留该确切选择:

{
  "name": "inspect_go_binary",
  "arguments": { "path": "/artifacts/application" }
}

对于构建身份和数量统计,请选择 detail: "summary"。MCP 保留相同的完整 Evidence,并返回 normalized_result.parent_evidence_id。无需重新打开文件即可读取选定的依赖版本:

{
  "name": "inspect_analysis_view",
  "arguments": {
    "source": {
      "kind": "retained-evidence",
      "evidence_id": "ev_<parent digest>"
    },
    "view": {
      "kind": "go",
      "collection": "dependencies",
      "paths": ["golang.org/x/crypto"],
      "fields": ["path", "version", "replacement"],
      "offset": 0,
      "limit": 10
    }
  }
}

Go 视图支持 dependencies(精确的 paths)和 settings(精确的 keys)、可选的原始 indices、字段选择以及分页。过滤器取交集;空过滤器数组不选择任何行,fields: [] 仅返回行标识。每行保留其原始 index,作用域限定于父 Evidence 和集合;重复的模块路径和设置键保持不同的索引。分页偏移量对匹配的记录计数。即使遍历完所有保留的行,也不能确认运行时依赖的完整性。原始字节、未知行以及所有完整元数据都保留在父级中,并可导出为 Evidence 包。

一次性 CLI 摘要会在返回投影之前保存完整的 Evidence:

rea inspect-go-binary ./application --detail summary --evidence_output ./go-evidence.json --json

--evidence_output 是 CLI 摘要交付所必需的,并且绝不会覆盖现有文件。默认的 CLI/MCP 回复保持完整。

已测量的工作流 包括目录的重复执行和额外调用。身份/数量类问题适合使用单个摘要。在测试的 Codex 完整目录配置中,针对一个涉及身份和单个依赖的复合问题,使用一次完整检查比使用摘要加后续查询在捕获的请求 JSON 中消耗更少的 token。完整回复对初始问题仍然有用;保留的视图支持后续的选择性读取。Token 数字是序列化估计值,而非模型实际用量。

观测结果

内联的 Evidence 结果包含工件路径、SHA-256、字节长度、容器格式、架构、字长和字节序。可识别的 build_info 记录包含:

  • go_version:作为嵌入的 UTF-8 文本保留,而不是强制转换为语义化版本;当嵌入的字节不是 UTF-8 时为 null;
  • go_version_bytes_base64:保留编译器字符串字节的精确内容;
  • 头部、编译器字符串和模块字符串的精确文件偏移量和字节长度;
  • module_text:解码后的模块信息主体;当完整主体无法以 UTF-8 表示时为 null;
  • module_bytes_base64:包含 Go 帧格式的原始模块字符串字节;
  • module.path:嵌入的包路径;
  • module.main:主模块的路径、版本、校验和以及可选的替换项;
  • module.dependencies:包含相同的字段及其原始顺序;
  • module.settings:保留有序的键/值条目和重复键;
  • module.unparsed_lines、module.unparsed_line_bytes_base64 和 module.complete:后者指示是否解析了每一条存在的模块文本行。它并不确认依赖清单是完整的。

缺失的校验和为 null;空字段以及开发/本地替换版本保持不变。当存在 GOOS、GOARCH 或 vcs.revision 等构建设置时,会如实报告。它们的缺失并不能确认构建选择。Go 字符串可能包含任意字节。非 UTF-8 记录仍可通过 base64 形式使用,同时其他可解码的模块记录仍会被报告;读取器不会为这些字符串插入替换字符,也不会因此拒绝整个工件。

当未解码到主模块(mod)记录时,module.main 为 null,依赖覆盖情况未知。成功解码的依赖记录仍然可见。GOPATH 模式下的构建可能只包含包 path 和构建设置;其空依赖数组并不能确认不存在依赖。结果的局限性说明中明确指出了这一点。模块模式下,如果存在主模块记录但没有依赖记录,则观测到的依赖列表为空。

支持边界

内置的 TypeScript 读取器支持 ELF、PE 和瘦 Mach-O 镜像,以及通用 Mach-O 的单个选定切片,支持 Go 的内联或历史指针式 build-info 编码。源范围引用原始的稳定文件快照,包括指针支持的字符串。共享的原生容器负责地址映射,包括文件支持的 PE 头。当描述符或字符串的虚拟地址映射到物理上连续且具有相同转换的文件字节时,它们可以跨越相邻映射。间隙、冲突的别名、零填充别名和非连续的字符串源字节无法建立单一源范围,因此会被拒绝。原生导出的 C 字符串使用相同的映射检查,但可以连接多个源块,因为它们的结果没有单跨度源契约。传统指针支持的字段按 Go 的 build-info 记录声明的宽度解码,与镜像的 ELF 类别无关。它不会将任意字节字符串扫描为编译器元数据。

遗留的字符串描述符和内容可以使用声明的文件支持的 PE 头。当描述符或字符串的虚拟范围覆盖所有请求的字节并标识一个连续的文件范围时,它也可以跨越相邻的加载器映射。间隙、冲突的文件别名和非空零填充重叠仍然无效。发现策略和总计 1 MiB 的字符串内容上限保持不变。这些是对 REA 原生映射事实的静态读取;它们并不确立 Windows/Linux 加载行为,也不提供与 Go 标准读取器的对等性,后者的 Go 1.24.0 ELF/PE 读取器 在单个段或节内读取。历史性的双字字符串描述符遵循 Go 1.17.13 读取器。

通用(FAT)Mach-O 需要 architecture(x86、x86_64、arm 或 arm64;CLI 为 --architecture)。REA 自行读取 FAT 表,无需 lipo,并根据该表验证所选切片的范围、对齐方式和 Mach-O 头 CPU。结果将通用文件保留为 artifact(其 SHA-256 和大小),添加 selected_slice(包含切片偏移量、长度、原始 CPU 类型/子类型和 FAT 表摘要),并将每个源范围报告为该切片内的文件偏移量。如果没有 architecture,或者文件没有此类切片或有多个切片,请求将在 architecture 上失败,并列出存在的切片。任何其他镜像上的 architecture 都会被拒绝而非忽略。

对于没有命名 build-info 节的 ELF 镜像,发现过程会按程序头顺序检查每个非空、可写、不可执行的加载段。这包括在后期的数据段中包含元数据的无节 PIE 镜像。命名节保持优先,且对齐、文件映射和记录验证仍然是必需的。当 ELF 节名称不可读时,限制项会报告该覆盖缺口;回退搜索策略不变。

命名的 ELF 或 Mach-O build-info 节会选择记录的发现范围。对于内联编码,后续的版本和模块字符串可以继续延伸出该节,进入其文件支持的加载映射;这些字节仍会根据该映射和现有的聚合字符串上限进行检查。

历史上的无模块 Go 二进制文件可以将空的模块字符串头存储在声明为零初始化的虚拟内存中,而不是文件支持的字节中。仅当完整的可选模块头位于该内存中且没有冲突的文件映射时,读取器才会识别这种情况。其模块内容为空,module_location 为零字节,锚定在包含模块头指针的 build-info 字段处。编译器字符串和其他未映射的指针仍然是严格的文件支持读取。

build_info: null 表示在受检镜像中未找到可识别的记录。这并不证明该二进制文件不是 Go。剥离(stripping)、旧构建、故意移除和混淆都可能限制元数据。格式错误的受支持容器或可识别的 build-info 记录会返回输入格式失败。不支持的容器会收到单独的 unsupported-target 失败。

符号链接和非普通文件会被拒绝。共享的稳定读取器会在采集期间检测替换以及观察到的就地更改。文件缺失、主机权限拒绝、工件更改和取消各自保留不同的错误。所选文件永远不会被修改;此检查不会创建临时文件、不会启动子进程,也不会访问任何网络端点。

超过 256 MiB 的输入会返回 resource_constraint,其中 resource 为 file-size,reported_limits.maximum_input_bytes 为报告的限制值。请在该固定配额内选择合适的输入;更改输出写入或传输预算并不会使其被接受。

资源保护将所选文件和累计头搜索各自限制为 256 MiB,将聚合的内嵌字符串内容限制为 1 MiB(varint 长度前缀属于帧格式,不计入此配额),将结构表解码限制为 16 MiB,将完整的规范化元数据报告限制为 8 MiB。内联字符串还必须适合其实际映射的源范围。具有相同虚拟对齐方式的相同搜索跨度只搜索一次;部分重叠的跨度会消耗累计搜索预算,并在预算耗尽时以 CPU 资源约束失败。过大的结果会直接失败,不会部分成功。MCP 还应用其 响应传输预算,该预算同时计入文本和结构化内容;在元数据限制内的报告仍可能需要从保留的 Evidence 中导出。这些限制不是操作系统内存或 CPU 隔离。

嵌入的元数据是文件内容的证据。它不能验证编译器、依赖项、提交或供应链,也不能确立运行时行为。函数名称、源映射、类型和反编译代码不在该工具的覆盖范围内。当这些问题需要反汇编器时,请使用原生工作流。

真实生产者验证

npm run verify:go:binary 通过公共 CLI 和 MCP 运行编译器构建的测试夹具,并将其元数据与 Go 标准的 debug/buildinfo 读取器进行比较。验证流水线需要 Go;正常检查则不需要。

报告中的读取器架构名称逐字保留。证据主体使用已识别的规范系列:386 映射到 x86,amd64 映射到 x86_64,ppc 映射到 powerpc。未知系列(如 ppc64)仍然保持未知,而不会从相关拼写中推断出来。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 rea2/rea