The relocation formats REL and RELA for ELF are inefficient. In a release build of Clang for x86-64, .rela.* sections consume a significant portion (approximately 20.9%) of the file size. I have developed an alternative relocation format (tentatively named RELLEB) for LLVM/Clang/lld, which yields a significant reduction of 16.7%! (.o file size) Elf32_Rel and Elf32_Rela sacrifice flexibility to maintain a smaller size, limiting relocation types to a maximum of 255. RELLEB allows 2**32 relocation types, aligning with Elf64_Rel/Elf64_Rela. --- I have analyzed many architectures including Arm (AArch32/AArch64), Power, RISC-V, MIPS, RISC-V, z/Architecture, and x86, written a detailed analysis of the size problem and my solution at https://maskray.me/blog/2024-03-09-a-compact-relocation-format-for-elf , created a generic ABI proposal https://groups.google.com/g/generic-abi/c/yb0rjw56ORw and an LLVM proposal https://discourse.llvm.org/t/rfc-relleb-a-compact-relocation-format-for-elf/77600 --- For binutils, we would need at least these pieces: * ld + handle SHT_RELLEB input sections + -r: copy SHT_RELLEB and rewrite + (optional; dynamic relocations) -z relleb: use .relleb.dyn instead of .rel.dyn/.rela.dyn for dynamic relocations. Can be used together with --pack-dyn-relocs=relr * readelf + -S: recognize SHT_RELLEB + -d: recognize DT_RELLEB + -r: dump SHT_RELLEB sections + (optional: if DT_RELLEB is accepted) dump DT_RELLEB table * objcopy + objcopy seems to convert SHT_REL to SHT_RELA (https://sourceware.org/bugzilla/show_bug.cgi?id=28035). If SHT_RELLEB is added, we will need to disable unneeded SHT_RELLEB => SHT_RELA conversion:) * objdump + -r: dump DT_RELLEB + -d -r: inline relocations
The format was tentatively named RELLEB. As I refine the original pure LEB-based format, “RELLEB” might not be the most fitting name. I have switched to SHT_CREL/DT_CREL/.crel and updated https://maskray.me/blog/2024-03-09-a-compact-relocation-format-for-elf https://groups.google.com/g/generic-abi/c/yb0rjw56ORw/m/eiBcYxSfAQAJ build | format | `.o size` | `size(.rel*)` | .o size decrease --------------------------------+-----------------+-------------+---------------+----------------- -O3 | RELA | 136012504 | 28235448 | -O3 | CREL | 111583312 | 3806234 | 18.0% aarch64 -O3 | RELA | 124965808 | 25855800 | aarch64 -O3 | CREL | 102529784 | 3388307 | 18.0% riscv64 -O3 | RELA | 227189744 | 91396344 | riscv64 -O3 | CREL | 149343352 | 13549699 | 34.3% -O1 -g | RELA | 1506173760 | 340965576 | -O1 -g | CREL | 1202445768 | 37237274 | 20.2% -O3 -g -gpubnames -gsplit-dwarf | RELA | 549003848 | 104227128 | -O3 -g -gpubnames -gsplit-dwarf | CREL | 459768736 | 14992114 | 16.3%
Sounds very interesting. Do you have binutils diff/patch to test it? I mean, compiling llvm takes hours, and compiling binutils takes minutes. That's 'subtle' difference.