Bug 31475

Summary: binutils: Support CREL relocation format
Product: binutils Reporter: Fangrui Song <i>
Component: binutilsAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: jremus, oset, sam, trass3r
Priority: P2    
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Fangrui Song 2024-03-12 04:27:24 UTC
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
Comment 1 Fangrui Song 2024-03-23 00:15:01 UTC
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%
Comment 2 oset 2024-05-16 18:16:05 UTC
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.