[链接器的世界-实验篇02] 符号与重定位记录:目标文件留下的待办事项
本实验把符号表与 RELA 解码为输入记录,交给后续阶段选择定义、安排地址和修补引用。两种 24 字节记录的字段见原理篇 02 的符号表与重定位表。
起点:class2 代码与测试,位于 private 仓库,需要访问权限。复用 class0/class1 的范围、节与字符串访问,在 class2 crate 的库接口中实现两个接口,不使用外部 ELF 解析库。
实现任务
| 任务 | 接口 | 要达到的结果 |
|---|---|---|
| C2.1 | symbols | 读取指定 SYMTAB,关联名字,保留 binding/type/visibility 与定义、值、大小 |
| C2.2 | relocations | 读取指定 RELA,验证符号归属,保留目标偏移、种类、符号下标与有符号加数 |
接口签名见 class2 crate 的公开 API,字段要求和诊断顺序见 class2 README。两个接口的 index 都是当前文件的节列表下标。Symbol.name 借用该 input 中关联字符串表的字节;返回的记录不能混用另一文件的下标。
SYMTAB 的 sh_link 选择名字表,sh_info 划分 LOCAL 与非 LOCAL;RELA 的 sh_link 选择符号表,sh_info 选择被修补节。r_info 中的符号下标只属于这张关联符号表,不是全局名称编号。
可以把一条记录具体展开:若当前对象的第 3 项是 SHT_SYMTAB,其 sh_link = 2,则 st_name 都在第 2 项字符串表中解释;若第 5 项是 SHT_RELA,它的 sh_link = 3、sh_info = 1,则每条 r_info 的符号下标都索引第 3 项符号表,而 r_offset 指向第 1 项被修补节。换入另一个对象后,即使名字相同,这些数字也必须重新按新对象的表解释。
第 0 个符号必须完整的 24 字节全零;空符号表非法,空 RELA 则可以合法,但仍需校验它的元数据和关联表。SHT_REL 明确拒绝。未知符号属性与重定位种类先保留;本章不应用补丁,因此不提前用某一种写入宽度判定 r_offset。
重定位的 sh_link 必须先指向 SHT_SYMTAB;下标越界返回 InvalidIndex,指向其他节类型返回 WrongSectionType,之后才调用 symbols 验证符号表。sh_info 指向非空目标节,不能把它误当成重定位表中的记录下标。
验收及其含义
在克隆后的仓库根目录、原生 x86-64 Linux 上执行:
cargo test --locked -p class0 -p class1 -p class2cargo test --locked -p class0 -p class1 -p class2 --releasepython3 scripts/grade.py class2合同测试检查全宽记录、特殊定义、局部顺序、名字、空项、截断与表间归属。原生测试汇编一个未解析调用,沿该 RELA 自己的 sh_link 找符号表,确认符号和加数被正确解码,不假设汇编器使用固定表下标。
通过说明引用记录能够准确表达输入;它不会证明被引用名称已有定义,也不会写入运行地址。