# 归档比较与多方言兼容

GNU 用独立名称表和偏移引用保存长名称，BSD 将名称嵌入成员，Darwin 还可能将对齐字节
计入成员数据大小。符号索引保存符号名到成员头部的绝对偏移，随着名称编码、索引宽度
或成员布局改变而变化。MoonAr 分开处理物理记录与逻辑成员，原始字节始终可观察。

## 兼容层的职责

1. 检查头部、数值与成员边界，保留特殊记录和原始字节。
2. 解析 GNU 引用与 BSD 内嵌名称，确定名称和数据范围。
3. 解码 GNU 32/64 位及 BSD/Darwin 32/64 位索引，检查字节序、计数、字符串和填充。
4. 将绝对偏移转换为普通成员索引，拒绝指向数据区、头部中间或特殊记录的引用。
5. 保留符号名及引用字段的源偏移，使诊断可以直接对应原文件。

BSD 字节序没有统一的显式标记。解析器分别验证两种解释，只接受唯一有效的结果，或
结果相同的中性解释。两种结构均有效但映射不同的归档返回 `AR010`；测试包含这样的
构造输入。空索引不会被强行标为某个字节序。

## 比较层的职责

物理比较包含名称表与符号表的原始字节，适合检查制品是否完全重现。
逻辑比较匹配普通成员，再将旧索引引用沿成员配对转换到新归档，比较符号到成员的关系。
同名符号的目标次序保留，避免漏报优先目标变化。

重名组先用完整内容匹配，再处理剩余项。哈希只用于查找，碰撞后仍检查完整字节；
使用字节视图避免复制载荷，不构造二次空间的对齐矩阵。候选无法唯一识别时，结果
保留稳定配对并列出歧义，不能从相同内容推断历史身份。

## 可复现案例

| 输入变化 | 结果 | 验证位置 |
| --- | --- | --- |
| 相同长名称和数据改用 GNU/BSD 编码 | 字节不同，逻辑内容和映射相同 | `logical_wbtest.mbt`、独立工具脚本 |
| 两个不同内容的同名成员前插入新项 | 定位新增项，原载荷不误报修改 | 同上，覆盖四种工具布局 |
| 同名成员交换位置 | 顺序变化，载荷不变 | 同上 |
| 多个同名候选无法唯一识别 | 稳定配对和 `ambiguities` | `logical_wbtest.mbt` |
| 索引宽度或布局变化 | 原始索引字节不同，成员映射可保持相同 | 合成测试、LLVM 64 位索引 |
| 同名符号的目标次序交换 | `symbols_equal=false` | `logical_wbtest.mbt` |
| 符号指向无效头部 | `AR009` 和引用字段偏移 | 索引测试、真实归档变异 |
| 只改变时间戳 | 内容相同、元数据不同 | 真实 C 对象和示例 |
| Darwin 填充计入数据大小 | 保留实际提取字节 | LLVM 提取对照和回归测试 |

独立对照从本项目编写的文本和 C 源码生成归档，使用 GNU/LLVM 的成员列举、提取和
GNU nm 的归档索引或原始对象符号核对结果。旧版 GNU nm 不显示 BSD armap 时，使用
原始对象的已定义外部符号及其输入成员作为独立参照。

GNU/Darwin 64 位索引使用 LLVM 的 `SYM64_THRESHOLD` 测试开关生成小文件，避免数 GiB
填充。开关和布局依据见
[LLVM ArchiveWriter](https://github.com/llvm/llvm-project/blob/llvmorg-18.1.3/llvm/lib/Object/ArchiveWriter.cpp)。

## 判断边界

Darwin 数据内的填充与真实文件末尾换行不可无条件区分，逻辑比较保留它们。
Darwin 确定性重名归档可能调整时间戳，内容匹配后仍报告真实元数据变化。
对象内部定义、机器码及 ABI 不属于比较范围；索引结构有效不代表链接成功。
CLI 使用完整文件的内存输入，资源预算约束解析阶段；输出和副本也需要额外内存。
