这篇文章介绍了 CREL(之前称为 RELLEB),一种新的重定位格式,提供了惊人的大小缩减(我的 fork 中的 LLVM 实现)。
ELF 设计与重定位的问题
- ELF 的设计强调控制结构的自然大小和对齐准则,促进了随机访问的便利性,但对于重定位来说存在显著缺点,如
Elf64_Rela
结构较大,Elf32_Rel
和Elf32_Rela
为保持较小尺寸牺牲了灵活性,限制了重定位类型。 - WebAssembly 的对象文件格式使用 LEB128 编码重定位和其他控制结构,在大小上具有显著优势。
压缩重定位与 CREL 重定位格式
- 标准
SHF_COMPRESSED
特性可用于调试部分,也可扩展到重定位部分,开发了 Clang/lld 原型来压缩SHT_RELA
部分,压缩后的SHT_RELA
部分占用sizeof(Elf64_Chdr) + size(compressed)
字节,在有许多较小重定位部分时可显著减少开销。 - CREL 是一种新的更紧凑的重定位格式,旨在替代 REL 和 RELA,其设计注重简单性,使用字节编码,避免复杂压缩技术。
SHT_CREL
部分(首选名称:.crel<name>
)包含紧凑的重定位条目,解码为Elf32_Rela
或Elf64_Rela
,其内容包括 ULEB128 编码的重定位计数、r_offset
等字段的编码,在多个方面进行了优化设计,如重定位计数使用 ULEB128 便于高效检索,移位偏移用于提高 64 位数据部分的编码效率,添加位标志用于平衡动态重定位的效率等。
LEB128 与其他编码方案比较
- LEB128 是常用的字节编码方案,在大多数整数适合一两个字节时具有优势,避免了移位操作。比较了多种可变长度整数编码方案,如 PrefixVarInt、VLQ 等,发现它们在对象文件中的优势不明显,LEB128 更适合。
实验结果
- 在不同架构和优化级别下进行实验,比较了 RELA 和 CREL 的文件大小,CREL 在大多数情况下都能实现显著的大小缩减,例如在 x86_64 -O3 构建中,文件大小减少了 18.0%,在 riscv64 -O3 构建中减少了 34.3%。
- 对动态重定位进行了研究,认为 CREL 能较好地压缩动态重定位,但仍有改进空间,提出了一种可能的通用 RELR 格式来更好地利用动态重定位的特性。
链接器相关注意事项
--emit-relocs
和-r
需要组合重定位部分,处理符号索引和添加项的变化,对于.eh_frame
等特殊部分需要特殊处理。- 对于某些未知的节类型,链接器可能会报错,如在使用
SHT_CREL
时,较旧的 lld 和 mold 可能不会报错。 - mips64el 的
r_info
存在问题,若采用 CREL 可借此机会进行修复。
数据压缩
- 分析了 lld 18 中的可重定位文件,发现 CREL 在压缩 RELA 和 CREL 重定位结合部分时表现出色,甚至优于 RELA 压缩后的结果,动态重定位也值得研究。
CREL 提案
- 在通用 ABI 中提出了 CREL 的相关修改,包括新增节类型
SHT_CREL
、特殊节.crelname
的定义、重定位条目结构的修改等,以及对动态数组标签DT_CREL
和DT_PLTREL
等的更新。
已放弃的 RELLEB 提案(最后修订)
- 介绍了之前的 RELLEB 提案的相关内容,与 CREL 类似但在编码方式上有所不同。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。