用于 ELF 的紧凑重定位格式

这篇文章介绍了 CREL(之前称为 RELLEB),一种新的重定位格式,提供了惊人的大小缩减(我的 fork 中的 LLVM 实现)。

ELF 设计与重定位的问题

  • ELF 的设计强调控制结构的自然大小和对齐准则,促进了随机访问的便利性,但对于重定位来说存在显著缺点,如Elf64_Rela结构较大,Elf32_RelElf32_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_RelaElf64_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_CRELDT_PLTREL等的更新。

已放弃的 RELLEB 提案(最后修订)

  • 介绍了之前的 RELLEB 提案的相关内容,与 CREL 类似但在编码方式上有所不同。
阅读 12
0 条评论