Skip to content

feat: Support -z pack-relative-relocs#1701

Draft
mati865 wants to merge 7 commits intowild-linker:mainfrom
mati865:push-ruqzpzktuvvm
Draft

feat: Support -z pack-relative-relocs#1701
mati865 wants to merge 7 commits intowild-linker:mainfrom
mati865:push-ruqzpzktuvvm

Conversation

@mati865
Copy link
Member

@mati865 mati865 commented Mar 17, 2026

Doesn't work yet:

./a.out: error while loading shared libraries: ./a.out: DT_RELR without GLIBC_ABI_DT_RELR dependency

I haven't yet figured out how to cleanly synthesise GLIBC_ABI_DT_RELR version for __libc_start_main symbol. I'd prefer to avoid matching that symbol by the name, but there might be no other choice.

@mati865
Copy link
Member Author

mati865 commented Mar 17, 2026

Ah, I have misunderstood that part. That version has to be just declared, not assigned to any symbol.

@mati865
Copy link
Member Author

mati865 commented Mar 17, 2026

It works now but doesn't support the major selling point of RELR which is compacting of the addresses via bitmaps. I'm not sure how to approach that as we need sorted entries before they are written for it work (use a temp buffer?). Currently, I'm working around the problem by sorting the entries after they are already written.

Clang release (without debuginfo) builds without and with -z pack-relative-relocs:

❯ ls bin*
.rwxr-xr-x 248M mateusz 17 mar 17:37  bin.default-ld
.rwxr-xr-x 248M mateusz 17 mar 17:37  bin.default-wild
.rwxr-xr-x 242M mateusz 17 mar 17:38  bin.pack-ld
.rwxr-xr-x 244M mateusz 17 mar 17:45  bin.pack-wild

Even without the compaction this is a small win to the size.

This is how compacted vs non-compacted entries look like:

❯ readelf -Wr bin.pack-ld | rg relr -A 5
Relocation section '.relr.dyn' at offset 0x71f100 contains 7264 entries which relocate 273137 locations:
Index: Entry            Address           Symbolic Address
0000:  000000000c8a8940 000000000c8a8940  __frame_dummy_init_array_entry
0001:  ffffffffffffffff 000000000c8a8948  __frame_dummy_init_array_entry + 0x8
                        000000000c8a8950  __frame_dummy_init_array_entry + 0x10
                        000000000c8a8958  __frame_dummy_init_array_entry + 0x18

❯ readelf -Wr bin.pack-wild | rg relr -A 5
Relocation section '.relr.dyn' at offset 0x70f868 contains 269508 entries which relocate 269508 locations:
Index: Entry            Address           Symbolic Address
0000:  000000000ca36288 000000000ca36288  __frame_dummy_init_array_entry
0001:  000000000ca36290 000000000ca36290  __frame_dummy_init_array_entry + 0x8
0002:  000000000ca36298 000000000ca36298  __frame_dummy_init_array_entry + 0x10
0003:  000000000ca362a0 000000000ca362a0  __frame_dummy_init_array_entry + 0x18
Performance impact is not bad considering the sort workaround
❯ OUT=/tmp/bin powerprofilesctl launch -p performance hyperfine -w 5 './run-with ~/Projects/wild/target/release/wild' './run-with ~/Projects/wild/target/release/wild -z pack-relative-relocs' './run-with ld.bfd' './run-with ld.bfd -z pack-relative-relocs' './run-with ~/Projects/wild/target/debug/wild' './run-with ~/Projects/wild/target/debug/wild -z pack-relative-relocs'
Benchmark 1: ./run-with ~/Projects/wild/target/release/wild
  Time (mean ± σ):      55.3 ms ±   1.8 ms    [User: 1.0 ms, System: 1.3 ms]
  Range (min … max):    52.4 ms …  59.9 ms    51 runs

Benchmark 2: ./run-with ~/Projects/wild/target/release/wild -z pack-relative-relocs
  Time (mean ± σ):      56.3 ms ±   1.1 ms    [User: 1.3 ms, System: 1.0 ms]
  Range (min … max):    54.4 ms …  60.7 ms    52 runs

Benchmark 3: ./run-with ld.bfd
  Time (mean ± σ):      1.853 s ±  0.052 s    [User: 1.391 s, System: 0.454 s]
  Range (min … max):    1.730 s …  1.925 s    10 runs

Benchmark 4: ./run-with ld.bfd -z pack-relative-relocs
  Time (mean ± σ):      1.987 s ±  0.046 s    [User: 1.541 s, System: 0.440 s]
  Range (min … max):    1.882 s …  2.062 s    10 runs

Benchmark 5: ./run-with ~/Projects/wild/target/debug/wild
  Time (mean ± σ):     320.7 ms ±   3.2 ms    [User: 1.7 ms, System: 1.1 ms]
  Range (min … max):   314.1 ms … 326.7 ms    10 runs

Benchmark 6: ./run-with ~/Projects/wild/target/debug/wild -z pack-relative-relocs
  Time (mean ± σ):     424.5 ms ±   3.7 ms    [User: 1.3 ms, System: 1.4 ms]
  Range (min … max):   418.2 ms … 430.8 ms    10 runs

Summary
  ./run-with ~/Projects/wild/target/release/wild ran
    1.02 ± 0.04 times faster than ./run-with ~/Projects/wild/target/release/wild -z pack-relative-relocs
    5.80 ± 0.20 times faster than ./run-with ~/Projects/wild/target/debug/wild
    7.67 ± 0.26 times faster than ./run-with ~/Projects/wild/target/debug/wild -z pack-relative-relocs
   33.48 ± 1.44 times faster than ./run-with ld.bfd
   35.90 ± 1.43 times faster than ./run-with ld.bfd -z pack-relative-relocs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant