[lld] [ELF] Add -z sort-thunks to sort thunks by destination (PR #211721)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 25 16:07:02 PDT 2026
================
@@ -0,0 +1,102 @@
+# REQUIRES: aarch64
+## -z sort-thunks orders a thunk section's forward thunks by descending destination so promoting
+## one to its long form cannot push another out of range. In creation order the promotions cascade,
+## one per pass, and exceed convergence limit (issue #61250).
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=aarch64 a.s -o a.o
+# RUN: ld.lld -T lds a.o -z sort-thunks -o out
+# RUN: llvm-objdump -d --no-show-raw-insn out | FileCheck %s
+## The default keeps creation order and does not converge.
+# RUN: not ld.lld -T lds a.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+# ERR: error: address assignment did not converge
+
+## One thunk section holds both directions: backward thunks first, in creation
+## order lo0, lo1, lo2 (they need no sorting), then forward thunks by descending
+## destination. The farthest forward thunks become long (ldr), nearer ones short (b).
+# CHECK: <__AArch64AbsLongThunk_lo0>:
+# CHECK: <__AArch64AbsLongThunk_lo1>:
+# CHECK: <__AArch64AbsLongThunk_lo2>:
+# CHECK: <__AArch64AbsLongThunk_hi43>:
+# CHECK-NEXT: ldr x16,
+# CHECK: <__AArch64AbsLongThunk_hi35>:
+# CHECK-NEXT: ldr x16,
+# CHECK: <__AArch64AbsLongThunk_hi34>:
+# CHECK-NEXT: b {{.*}} <hi34>
+# CHECK: <__AArch64AbsLongThunk_hi0>:
+
+## getDestVA keys a PLT-routed thunk on the PLT entry, not the symbol value. bar's thunk sorts after
+## the backward thunk to local cbwd; the symbol value 0 would place it backward and flip the order.
+# RUN: llvm-mc -filetype=obj -triple=aarch64 b.s -o b.o
+# RUN: ld.lld -shared b.o -o b.so
+# RUN: llvm-mc -filetype=obj -triple=aarch64 c.s -o c.o
+# RUN: ld.lld -T lds2 c.o b.so -z sort-thunks -o out2
+# RUN: llvm-objdump -d --no-show-raw-insn out2 | FileCheck %s --check-prefix=PLT
+# PLT: <__AArch64AbsLongThunk_cbwd>:
+# PLT: <__AArch64AbsLongThunk_bar>:
+
+#--- a.s
+.section .low,"ax",%progbits
+.rept 3
+.globl lo\+
+lo\+:
+ ret
+ .space 12
+.endr
+
+.text
+.globl _start
+_start:
+.rept 3
+ bl lo\+
+.endr
+.rept 44
+ bl hi\+
+ .space 12
+.endr
+
+.section .high,"ax",%progbits
+.rept 44
+ .globl hi\+
+hi\+:
+ ret
+ .space 12
+.endr
+
+#--- lds
+## .low sits far below .text, so lo<n> calls need (always long) backward thunks.
+## .high follows a gap tuned (688 = 44*16 - 16 + 12) so that, once the thunk
+## section shifts .high, only the farthest hi<i> is out of range; in creation
+## order each promotion then pushes out exactly one more.
+SECTIONS {
+ .low 0x10000 : { *(.low) }
+ .text 0x10000000 : { *(.text) }
+ . = . + 0x8000000 - 688;
----------------
MaskRay wrote:
done
https://github.com/llvm/llvm-project/pull/211721
More information about the llvm-commits
mailing list