Index: test/ELF/arm-thunk-linkerscript-dotexpr.s =================================================================== --- /dev/null +++ test/ELF/arm-thunk-linkerscript-dotexpr.s @@ -0,0 +1,79 @@ +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: . = SIZEOF_HEADERS; \ +// RUN: .text_low : { *(.text_low) *(.text_low2) . = . + 0x2000000 ; *(.text_high) *(.text_high2) } \ +// RUN: } " > %t.script +// RUN: ld.lld --script %t.script %t -o %t2 2>&1 +// RUN llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s +// RUN: llvm-objdump -d %t2 -start-address=148 -stop-address=188 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s +// RUN: llvm-objdump -d %t2 -start-address=33554620 -stop-address=33554654 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s + +// Test that range extension thunks can handle location expressions within +// a Section Description + .syntax unified + .section .text_low, "ax", %progbits + .thumb + .globl _start +_start: bx lr + .globl low_target + .type low_target, %function +low_target: + bl high_target + bl high_target2 + + .section .text_low2, "ax", %progbits + .thumb + .globl low_target2 + .type low_target2, %function +low_target2: + bl high_target + bl high_target2 +// CHECK1: Disassembly of section .text_low: +// CHECK1-NEXT: _start: +// CHECK1-NEXT: 94: 70 47 bx lr +// CHECK1: low_target: +// CHECK1-NEXT: 96: 00 f0 07 f8 bl #14 +// CHECK1-NEXT: 9a: 00 f0 0a f8 bl #20 +// CHECK1: low_target2: +// CHECK1-NEXT: 9e: 00 f0 03 f8 bl #6 +// CHECK1-NEXT: a2: 00 f0 06 f8 bl #12 +// CHECK1-NEXT: a6: 00 00 movs r0, r0 +// CHECK1: __Thumbv7ABSLongThunk_high_target: +// CHECK1-NEXT: a8: 40 f2 d1 0c movw r12, #209 +// CHECK1-NEXT: ac: c0 f2 00 2c movt r12, #512 +// CHECK1-NEXT: b0: 60 47 bx r12 +// CHECK1: __Thumbv7ABSLongThunk_high_target2: +// CHECK1-NEXT: b2: 40 f2 d9 0c movw r12, #217 +// CHECK1-NEXT: b6: c0 f2 00 2c movt r12, #512 +// CHECK1-NEXT: ba: 60 47 bx r12 + + .section .text_high, "ax", %progbits + .thumb + .globl high_target + .type high_target, %function +high_target: + bl low_target + bl low_target2 + + .section .text_high, "ax", %progbits + .thumb + .globl high_target2 + .type high_target2, %function +high_target2: + bl low_target + bl low_target2 + +// CHECK2: __Thumbv7ABSLongThunk_low_target: +// CHECK2-NEXT: 20000bc: 40 f2 97 0c movw r12, #151 +// CHECK2-NEXT: 20000c0: c0 f2 00 0c movt r12, #0 +// CHECK2-NEXT: 20000c4: 60 47 bx r12 +// CHECK2: __Thumbv7ABSLongThunk_low_target2: +// CHECK2-NEXT: 20000c6: 40 f2 9f 0c movw r12, #159 +// CHECK2-NEXT: 20000ca: c0 f2 00 0c movt r12, #0 +// CHECK2-NEXT: 20000ce: 60 47 bx r12 +// CHECK2: high_target: +// CHECK2-NEXT: 20000d0: ff f7 f4 ff bl #-24 +// CHECK2-NEXT: 20000d4: ff f7 f7 ff bl #-18 +// CHECK2: high_target2: +// CHECK2-NEXT: 20000d8: ff f7 f0 ff bl #-32 +// CHECK2-NEXT: 20000dc: ff f7 f3 ff bl #-26 Index: test/ELF/arm-thunk-linkerscript-large.s =================================================================== --- /dev/null +++ test/ELF/arm-thunk-linkerscript-large.s @@ -0,0 +1,179 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: .text 0x100000 : { *(.text) } \ +// RUN: .textl : { *(.text_l0*) *(.text_l1*) *(.text_l2*) *(.text_l3*) } \ +// RUN: .texth : { *(.text_h0*) *(.text_h1*) *(.text_h2*) *(.text_h3*) } \ +// RUN: }" > %t.script +// RUN: ld.lld --script %t.script %t -o %t2 2>&1 +// The output file is large, most of it zeroes. We dissassemble only the +// parts we need to speed up the test and avoid a large output file +// RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048594 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s +// RUN: llvm-objdump -d %t2 -start-address=2097152 -stop-address=2097160 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s +// RUN: llvm-objdump -d %t2 -start-address=17825796 -stop-address=17825806 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s +// RUN: llvm-objdump -d %t2 -start-address=33554436 -stop-address=33554446 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s +// RUN: llvm-objdump -d %t2 -start-address=34603008 -stop-address=34603022 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s +// RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651598 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s +// RUN: llvm-objdump -d %t2 -start-address=67108868 -stop-address=67108888 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s +// RUN: llvm-objdump -d %t2 -start-address=68157440 -stop-address=68157450 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s + +// Test the range extensions in a linker script where there are several +// OutputSections requiring range extension Thunks. We should be able to reuse +// Thunks between OutputSections but our placement of new Thunks is done on a +// per OutputSection basis + .syntax unified + +// Define a function that we can match with .text_l* aligned on a megabyte // boundary + .macro FUNCTIONL suff + .section .text_l\suff\(), "ax", %progbits + .thumb + .balign 0x100000 + .globl tfuncl\suff\() + .type tfuncl\suff\(), %function +tfuncl\suff\(): + bx lr + .endm + +// Define a function that we can match with .text_h* aligned on a megabyte +// boundary + .macro FUNCTIONH suff + .section .text_h\suff\(), "ax", %progbits + .thumb + .balign 0x100000 + .globl tfunch\suff\() + .type tfunch\suff\(), %function +tfunch\suff\(): + bx lr + .endm + + .section .text, "ax", %progbits + .thumb + .globl _start +_start: + bl tfuncl00 + // Expect a range extension thunk in .text OutputSection + bl tfunch31 +// CHECK1: Disassembly of section .text: +// CHECK1-NEXT: _start: +// CHECK1-NEXT: 100000: ff f0 fe ff bl #1048572 +// CHECK1-NEXT: 100004: 00 f0 00 f8 bl #0 +// CHECK1: __Thumbv7ABSLongThunk_tfunch31: +// CHECK1-NEXT: 100008: 40 f2 01 0c movw r12, #1 +// CHECK1-NEXT: 10000c: c0 f2 10 4c movt r12, #1040 +// CHECK1-NEXT: 100010: 60 47 bx r12 + FUNCTIONL 00 + // Create a range extension thunk in .textl + bl tfuncl24 + // We can reuse existing thunk in .text + bl tfunch31 +// CHECK2: Disassembly of section .textl: +// CHECK2-NEXT: tfuncl00: +// CHECK2-NEXT: 200000: 70 47 bx lr +// CHECK2-NEXT: 200002: ff f2 ff d7 bl #15728638 +// CHECK2-NEXT: 200006: ff f6 ff ff bl #-1048578 + FUNCTIONL 01 + FUNCTIONL 02 + FUNCTIONL 03 + FUNCTIONL 04 + FUNCTIONL 05 + FUNCTIONL 06 + FUNCTIONL 07 + FUNCTIONL 08 + FUNCTIONL 09 + FUNCTIONL 10 + FUNCTIONL 11 + FUNCTIONL 12 + FUNCTIONL 13 + FUNCTIONL 14 + FUNCTIONL 15 +// CHECK3: __Thumbv7ABSLongThunk_tfuncl24: +// CHECK3-NEXT: 1100004: 40 f2 01 0c movw r12, #1 +// CHECK3-NEXT: 1100008: c0 f2 a0 1c movt r12, #416 +// CHECK3-NEXT: 110000c: 60 47 bx r12 + FUNCTIONL 16 + FUNCTIONL 17 + FUNCTIONL 18 + FUNCTIONL 19 + FUNCTIONL 20 + FUNCTIONL 21 + FUNCTIONL 22 + FUNCTIONL 23 + FUNCTIONL 24 + FUNCTIONL 25 + FUNCTIONL 26 + FUNCTIONL 27 + FUNCTIONL 28 + FUNCTIONL 29 + FUNCTIONL 30 +// CHECK4: __Thumbv7ABSLongThunk_tfuncl00: +// CHECK4-NEXT: 2000004: 40 f2 01 0c movw r12, #1 +// CHECK4-NEXT: 2000008: c0 f2 20 0c movt r12, #32 +// CHECK4-NEXT: 200000c: 60 47 bx r12 + FUNCTIONL 31 + // Create range extension thunks in .textl + bl tfuncl00 + bl tfuncl24 + // Shouldn't need a thunk + bl tfunch00 +// CHECK5: tfuncl31: +// CHECK5-NEXT: 2100000: 70 47 bx lr +// CHECK5-NEXT: 2100002: ff f6 ff ff bl #-1048578 +// CHECK5-NEXT: 2100006: ff f4 fb f7 bl #-7340042 +// CHECK5-NEXT: 210000a: ff f0 f9 ff bl #1048562 + FUNCTIONH 00 + // Can reuse existing thunks in .textl + bl tfuncl00 + bl tfuncl24 + // Shouldn't need a thunk + bl tfuncl31 +// CHECK6: tfunch00: +// CHECK6-NEXT: 2200000: 70 47 bx lr +// CHECK6-NEXT: 2200002: ff f5 ff ff bl #-2097154 +// CHECK6-NEXT: 2200006: ff f7 fb df bl #-8388618 +// CHECK6-NEXT: 220000a: ff f6 f9 ff bl #-1048590 + FUNCTIONH 01 + FUNCTIONH 02 + FUNCTIONH 03 + FUNCTIONH 04 + FUNCTIONH 05 + FUNCTIONH 06 + FUNCTIONH 07 + FUNCTIONH 08 + FUNCTIONH 09 + FUNCTIONH 10 + FUNCTIONH 11 + FUNCTIONH 12 + FUNCTIONH 13 + FUNCTIONH 14 + FUNCTIONH 15 + FUNCTIONH 16 + FUNCTIONH 17 + FUNCTIONH 18 + FUNCTIONH 19 + FUNCTIONH 20 + FUNCTIONH 21 + FUNCTIONH 22 + FUNCTIONH 23 + FUNCTIONH 24 + FUNCTIONH 25 + FUNCTIONH 26 + FUNCTIONH 27 + FUNCTIONH 28 + FUNCTIONH 29 + FUNCTIONH 30 +// CHECK7: __Thumbv7ABSLongThunk_tfuncl00: +// CHECK7-NEXT: 4000004: 40 f2 01 0c movw r12, #1 +// CHECK7-NEXT: 4000008: c0 f2 20 0c movt r12, #32 +// CHECK7-NEXT: 400000c: 60 47 bx r12 +// CHECK7: __Thumbv7ABSLongThunk_tfunch00: +// CHECK7-NEXT: 400000e: 40 f2 01 0c movw r12, #1 +// CHECK7-NEXT: 4000012: c0 f2 20 2c movt r12, #544 +// CHECK7-NEXT: 4000016: 60 47 bx r12 + FUNCTIONH 31 +// expect Thunks in .texth + bl tfuncl00 + bl tfunch00 +// CHECK8: tfunch31: +// CHECK8-NEXT: 4100000: 70 47 bx lr +// CHECK8-NEXT: 4100002: ff f6 ff ff bl #-1048578 +// CHECK8-NEXT: 4100006: 00 f7 02 f8 bl #-1048572 Index: test/ELF/arm-thunk-linkerscript-orphan.s =================================================================== --- /dev/null +++ test/ELF/arm-thunk-linkerscript-orphan.s @@ -0,0 +1,64 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: .text_low 0x100000 : { *(.text_low) } \ +// RUN: .text_high 0x2000000 : { *(.text_high) } \ +// RUN: .data : { *(.data) } \ +// RUN: }" > %t.script +// RUN: ld.lld --script %t.script %t -o %t2 2>&1 +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s + .syntax unified + .section .text_low, "ax", %progbits + .thumb + .globl _start +_start: bx lr + .globl low_target + .type low_target, %function +low_target: + bl high_target + bl orphan_target +// CHECK: Disassembly of section .text_low: +// CHECK-NEXT: _start: +// CHECK-NEXT: 100000: 70 47 bx lr +// CHECK: low_target: +// CHECK-NEXT: 100002: 00 f0 03 f8 bl #6 +// CHECK-NEXT: 100006: 00 f0 06 f8 bl #12 +// CHECK-NEXT: 10000a: 00 00 movs r0, r0 +// CHECK: __Thumbv7ABSLongThunk_high_target: +// CHECK-NEXT: 10000c: 40 f2 01 0c movw r12, #1 +// CHECK-NEXT: 100010: c0 f2 00 2c movt r12, #512 +// CHECK-NEXT: 100014: 60 47 bx r12 +// CHECK: __Thumbv7ABSLongThunk_orphan_target: +// CHECK-NEXT: 100016: 40 f2 15 0c movw r12, #21 +// CHECK-NEXT: 10001a: c0 f2 00 2c movt r12, #512 +// CHECK-NEXT: 10001e: 60 47 bx r12 + .section .text_high, "ax", %progbits + .thumb + .globl high_target + .type high_target, %function +high_target: + bl low_target + bl orphan_target +// CHECK: Disassembly of section .text_high: +// CHECK-NEXT: high_target: +// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4 +// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12 +// CHECK: __Thumbv7ABSLongThunk_low_target: +// CHECK-NEXT: 2000008: 40 f2 03 0c movw r12, #3 +// CHECK-NEXT: 200000c: c0 f2 10 0c movt r12, #16 +// CHECK-NEXT: 2000010: 60 47 bx r12 + + .section orphan, "ax", %progbits + .thumb + .globl orphan_target + .type orphan_target, %function +orphan_target: + bl low_target + bl high_target +// CHECK: Disassembly of section orphan: +// CHECK-NEXT: orphan_target: +// CHECK-NEXT: 2000014: ff f7 f8 ff bl #-16 +// CHECK-NEXT: 2000018: ff f7 f2 ff bl #-28 + + .data + .word 10 Index: test/ELF/arm-thunk-linkerscript-sort.s =================================================================== --- /dev/null +++ test/ELF/arm-thunk-linkerscript-sort.s @@ -0,0 +1,71 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: .text 0x100000 : { *(SORT_BY_NAME(.text.*)) } \ +// RUN: }" > %t.script +// RUN: ld.lld --script %t.script %t -o %t2 2>&1 +// RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048584 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s +// RUN: llvm-objdump -d %t2 -start-address=16777220 -stop-address=16777230 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s + + .syntax unified + +// Test that linkerscript sorting does not apply to Thunks, we expect that the +// sort will reverse the order of sections presented here. + +// Define a function aligned on a megabyte boundary + .macro FUNCTION suff + .section .text.\suff\(), "ax", %progbits + .thumb + .balign 0x100000 + .globl tfunc\suff\() + .type tfunc\suff\(), %function +tfunc\suff\(): + bx lr + .endm + + FUNCTION 31 + FUNCTION 30 + FUNCTION 29 + FUNCTION 28 + FUNCTION 27 + FUNCTION 26 + FUNCTION 25 + FUNCTION 24 + FUNCTION 23 + FUNCTION 22 + FUNCTION 21 + FUNCTION 20 + FUNCTION 19 + FUNCTION 18 + FUNCTION 17 + FUNCTION 16 + FUNCTION 15 +// CHECK2: __Thumbv7ABSLongThunk_tfunc31: +// CHECK2-NEXT: 1000004: 40 f2 01 0c movw r12, #1 +// CHECK2-NEXT: 1000008: c0 f2 00 2c movt r12, #512 +// CHECK2-NEXT: 100000c: 60 47 bx r12 + FUNCTION 14 + FUNCTION 13 + FUNCTION 12 + FUNCTION 11 + FUNCTION 10 + FUNCTION 09 + FUNCTION 08 + FUNCTION 07 + FUNCTION 06 + FUNCTION 05 + FUNCTION 04 + FUNCTION 03 + FUNCTION 02 + FUNCTION 01 + .section .text.00, "ax", %progbits + .thumb + .globl _start +_start: +// Expect no range extension needed for tfunc01 and an extension needed for +// tfunc31 + bl tfunc01 + bl tfunc31 +// CHECK1: _start: +// CHECK1-NEXT: 100000: ff f0 fe ff bl #1048572 +// CHECK1-NEXT: 100004: ff f2 fe d7 bl #15728636 Index: test/ELF/arm-thunk-linkerscript.s =================================================================== --- /dev/null +++ test/ELF/arm-thunk-linkerscript.s @@ -0,0 +1,79 @@ +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: . = SIZEOF_HEADERS; \ +// RUN: .text_low : { *(.text_low) *(.text_low2) } \ +// RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \ +// RUN: } " > %t.script +// RUN: ld.lld --script %t.script %t -o %t2 2>&1 +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s + +// Simple test that we can support range extension thunks with linker scripts + .syntax unified + .section .text_low, "ax", %progbits + .thumb + .globl _start +_start: bx lr + .globl low_target + .type low_target, %function +low_target: + bl high_target + bl high_target2 + + .section .text_low2, "ax", %progbits + .thumb + .globl low_target2 + .type low_target2, %function +low_target2: + bl high_target + bl high_target2 + +// CHECK: Disassembly of section .text_low: +// CHECK-NEXT: _start: +// CHECK-NEXT: 94: 70 47 bx lr +// CHECK: low_target: +// CHECK-NEXT: 96: 00 f0 07 f8 bl #14 +// CHECK-NEXT: 9a: 00 f0 0a f8 bl #20 +// CHECK: low_target2: +// CHECK-NEXT: 9e: 00 f0 03 f8 bl #6 +// CHECK-NEXT: a2: 00 f0 06 f8 bl #12 +// CHECK-NEXT: a6: 00 00 movs r0, r0 +// CHECK: __Thumbv7ABSLongThunk_high_target: +// CHECK-NEXT: a8: 40 f2 01 0c movw r12, #1 +// CHECK-NEXT: ac: c0 f2 00 2c movt r12, #512 +// CHECK-NEXT: b0: 60 47 bx r12 +// CHECK: __Thumbv7ABSLongThunk_high_target2: +// CHECK-NEXT: b2: 40 f2 09 0c movw r12, #9 +// CHECK-NEXT: b6: c0 f2 00 2c movt r12, #512 +// CHECK-NEXT: ba: 60 47 bx r12 + + .section .text_high, "ax", %progbits + .thumb + .globl high_target + .type high_target, %function +high_target: + bl low_target + bl low_target2 + + .section .text_high, "ax", %progbits + .thumb + .globl high_target2 + .type high_target2, %function +high_target2: + bl low_target + bl low_target2 + +// CHECK: Disassembly of section .text_high: +// CHECK-NEXT: high_target: +// CHECK-NEXT: 2000000: 00 f0 06 f8 bl #12 +// CHECK-NEXT: 2000004: 00 f0 09 f8 bl #18 +// CHECK: high_target2: +// CHECK-NEXT: 2000008: 00 f0 02 f8 bl #4 +// CHECK-NEXT: 200000c: 00 f0 05 f8 bl #10 +// CHECK: __Thumbv7ABSLongThunk_low_target: +// CHECK-NEXT: 2000010: 40 f2 97 0c movw r12, #151 +// CHECK-NEXT: 2000014: c0 f2 00 0c movt r12, #0 +// CHECK-NEXT: 2000018: 60 47 bx r12 +// CHECK: __Thumbv7ABSLongThunk_low_target2: +// CHECK-NEXT: 200001a: 40 f2 9f 0c movw r12, #159 +// CHECK-NEXT: 200001e: c0 f2 00 0c movt r12, #0 +// CHECK-NEXT: 2000022: 60 47 bx r12