[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