// REQUIRES: aarch64
// RUN: rm -rf %t && split-file %s %t && cd %t
// RUN: llvm-mc -filetype=obj -triple=aarch64 asm -o a.o
// RUN: ld.lld --threads=1 --shared --script=lds a.o -o out.so --defsym absolute=0xf0000000
// RUN: llvm-objdump -d --no-show-raw-insn out.so | FileCheck %s
// RUN: llvm-objdump -d --no-show-raw-insn out.so | FileCheck %s --check-prefix=CHECK-PADS
// RUN: llvm-mc -filetype=obj -triple=aarch64 shared -o shared.o
// RUN: ld.lld --shared -o shared.so shared.o
// RUN: ld.lld shared.so --script=lds a.o -o exe --defsym absolute=0xf0000000
// RUN: llvm-objdump -d --no-show-raw-insn exe | FileCheck %s --check-prefix=CHECK-EXE
// RUN: llvm-objdump -d --no-show-raw-insn exe | FileCheck %s --check-prefix=CHECK-PADS
/// Test thunk generation when destination does not have a BTI compatible
/// landing pad. Linker must generate landing pad sections for thunks that use
/// indirect branches.
//--- asm
.section ".note.gnu.property", "a"
.p2align 3
.long 4
.long 0x10
.long 0x5
.asciz "GNU"
/// Enable BTI.
.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND.
.long 4
.long 1 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI.
.long 0
/// Short thunks are direct branches so we don't need landing pads. Expect
/// all thunks to branch directly to target.
.section .text.0, "ax", %progbits
.balign 0x1000
.global _start
.type _start, %function
_start:
bl bti_c_target
bl bti_j_target
bl bti_jc_target
bl paciasp_target
bl pacibsp_target
bl .text.2 + 0x4 // fn2
b .text.2 + 0x4 // fn2
bl fn1
b fn1
bl fn3
b fn3
bl fn4
b fn4
bl via_plt
/// We cannot add landing pads for absolute symbols.
bl absolute
/// padding so that we require thunks that can be placed after this section.
/// The thunks are close enough to the target to be short.
.space 0x1000
// CHECK-PADS-LABEL: <_start>:
// CHECK-PADS-NEXT: 10001000: bl 0x1000203c
// CHECK-PADS-NEXT: bl 0x10002040
// CHECK-PADS-NEXT: bl 0x10002044
// CHECK-PADS-NEXT: bl 0x10002048
// CHECK-PADS-NEXT: bl 0x1000204c
// CHECK-PADS-NEXT: bl 0x10002050
// CHECK-PADS-NEXT: b 0x10002050
// CHECK-PADS-NEXT: bl 0x10002054
// CHECK-PADS-NEXT: b 0x10002054
// CHECK-PADS-NEXT: bl 0x10002058
// CHECK-PADS-NEXT: b 0x10002058
// CHECK-PADS-NEXT: bl 0x1000205c
// CHECK-PADS-NEXT: b 0x1000205c
// CHECK-PADS-NEXT: bl 0x10002060
// CHECK-PADS-NEXT: bl 0x10002064
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 1000203c: b 0x18001000 <bti_c_target>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 10002040: b 0x18001008 <bti_j_target>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 10002044: b 0x18001010 <bti_jc_target>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 10002048: b 0x18001018 <paciasp_target>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 1000204c: b 0x18001020 <pacibsp_target>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 10002050: b 0x18001038 <fn2>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 10002054: b 0x18001034 <fn1>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 10002058: b 0x18001040 <fn3>
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 1000205c: b 0x18001050 <fn4>
// CHECK-LABEL: <__AArch64ADRPThunk_via_plt>:
// CHECK-NEXT: 10002060: b 0x18001080 <via_plt@plt>
// CHECK-LABEL: <__AArch64ADRPThunk_absolute>:
// CHECK-NEXT: 10002064: b 0x18001098 <absolute@plt>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 1000203c: b 0x18001000 <bti_c_target>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 10002040: b 0x18001008 <bti_j_target>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 10002044: b 0x18001010 <bti_jc_target>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 10002048: b 0x18001018 <paciasp_target>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 1000204c: b 0x18001020 <pacibsp_target>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 10002050: b 0x18001038 <fn2>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 10002054: b 0x18001034 <fn1>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 10002058: b 0x18001040 <fn3>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 1000205c: b 0x18001050 <fn4>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_via_plt>:
// CHECK-EXE-NEXT: 10002060: b 0x18001080 <via_plt@plt>
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_absolute>:
// CHECK-EXE-NEXT: 10002064: ldr x16, 0x1000206c <__AArch64AbsLongThunk_absolute+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 00 00 00 f0 .word 0xf0000000
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
.section .text.1, "ax", %progbits
/// These indirect branch targets already have a BTI compatible landing pad,
/// no alternative entry point required.
.hidden bti_c_target
.type bti_c_target, %function
bti_c_target:
bti c
ret
.hidden bti_j_target
.type bti_j_target, %function
bti_j_target:
bti j
ret
.hidden bti_jc_target
.type bti_jc_target, %function
bti_jc_target:
bti jc
ret
.hidden paciasp_target
.type paciasp_target, %function
paciasp_target:
paciasp
ret
.hidden pacibsp_target
.type pacibsp_target, %function
pacibsp_target:
pacibsp
ret
// CHECk-PADS-LABEL: <bti_c_target>:
// CHECK-PADS: 18001000: bti c
// CHECK-PADS-NEXT: ret
// CHECK-PADS-LABEL: <bti_j_target>:
// CHECK-PADS-NEXT: 18001008: bti j
// CHECK-PADS-NEXT: ret
// CHECK-PADS-LABEL: <bti_jc_target>:
// CHECK-PADS-NEXT: 18001010: bti jc
// CHECK-PADS-NEXT: ret
// CHECK-PADS-LABEL: <paciasp_target>:
// CHECK-PADS-NEXT: 18001018: paciasp
// CHECK-PADS-NEXT: ret
// CHECK-PADS-LABEL: <pacibsp_target>:
// CHECK-PADS-NEXT: 18001020: pacibsp
// CHECK-PADS-NEXT: ret
/// These functions do not have BTI compatible landing pads. Expect linker
/// generated landing pads for indirect branch thunks.
.section .text.2, "ax", %progbits
.hidden fn1
.type fn1, %function
fn1:
ret
.hidden fn2
.type fn2, %function
fn2:
ret
// CHECK-PADS-LABEL: <__AArch64BTIThunk_>:
// CHECK-PADS-NEXT: 18001028: bti c
// CHECK-PADS-NEXT: b 0x18001038 <fn2>
// CHECK-PADS-LABEL: <__AArch64BTIThunk_>:
// CHECK-PADS-NEXT: 18001030: bti c
// CHECK-PADS-LABEL: <fn1>:
// CHECK-PADS-NEXT: 18001034: ret
// CHECK-PADS-LABEL <fn2>:
// CHECK-PADS: 18001038: ret
/// Section with only one function at offset 0. Landing pad should be able to
/// fall through.
.section .text.3, "ax", %progbits
.hidden fn3
.type fn3, %function
fn3:
ret
// CHECK-PADS-LABEL: <__AArch64BTIThunk_>:
// CHECK-PADS-NEXT: 1800103c: bti c
// CHECK-PADS-LABEL: <fn3>:
// CHECK-PADS-NEXT: 18001040: ret
/// Section with only one function at offset 0, also with a high alignment
/// requirement. Check that we don't fall through into alignment padding.
.section .text.4, "ax", %progbits
.hidden fn4
.type fn4, %function
.balign 16
fn4:
ret
// CHECK-PADS-LABEL: <__AArch64BTIThunk_>:
// CHECK-PADS: 18001044: bti c
// CHECK-PADS-NEXT: b 0x18001050 <fn4>
// CHECK-PADS-NEXT: udf #0x0
// CHECK-PADS-LABEL: <fn4>:
// CHECK-PADS-NEXT: 18001050: ret
.section .long_calls, "ax", %progbits
.global long_calls
.type long_calls, %function
long_calls:
/// Expect thunk to target as targets have BTI or implicit BTI.
bl bti_c_target
bl bti_j_target
bl bti_jc_target
bl paciasp_target
bl pacibsp_target
/// Expect thunk to target a linker generated entry point with BTI landing pad.
/// Two calls to make sure only one landing pad is created.
bl .text.2 + 0x4 // fn2
b .text.2 + 0x4 // fn2
/// fn2 before fn1 so that landing pad for fn1 can fall through.
bl fn1
b fn1
bl fn3
b fn3
bl fn4
b fn4
/// PLT entries reachable via Thunks have a BTI c at the start of each entry
/// so no additional landing pad required.
bl via_plt
/// We cannot add landing pads for absolute symbols.
bl absolute
/// PLT entries have BTI at start.
// CHECK-LABEL: <via_plt@plt>:
// CHECK-NEXT: bti c
// CHECK-NEXT: adrp x16, 0x30000000
// CHECK-NEXT: ldr x17, [x16, #0x198]
// CHECK-NEXT: add x16, x16, #0x198
// CHECK-NEXT: br x17
// CHECK-NEXT: nop
// CHECK: <absolute@plt>:
// CHECK-NEXT: bti c
// CHECK-NEXT: adrp x16, 0x30000000
// CHECK-NEXT: ldr x17, [x16, #0x1a0]
// CHECK-NEXT: add x16, x16, #0x1a0
// CHECK-NEXT: br x17
// CHECK-NEXT: nop
// CHECK-EXE-LABEL: <via_plt@plt>:
// CHECK-EXE-NEXT: 18001080: bti c
// CHECK-EXE-NEXT: adrp x16, 0x30000000
// CHECK-EXE-NEXT: ldr x17, [x16, #0x1e8]
// CHECK-EXE-NEXT: add x16, x16, #0x1e8
// CHECK-EXE-NEXT: br x17
// CHECK-EXE-NEXT: nop
// CHECK-LABEL: <long_calls>:
// CHECK-NEXT: 30000000: bl 0x3000003c <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x30000048 <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x30000054 <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x30000060 <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x3000006c <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x30000078 <__AArch64ADRPThunk_>
// CHECK-NEXT: b 0x30000078 <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x30000084 <__AArch64ADRPThunk_>
// CHECK-NEXT: b 0x30000084 <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x30000090 <__AArch64ADRPThunk_>
// CHECK-NEXT: b 0x30000090 <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x3000009c <__AArch64ADRPThunk_>
// CHECK-NEXT: b 0x3000009c <__AArch64ADRPThunk_>
// CHECK-NEXT: bl 0x300000a8 <__AArch64ADRPThunk_via_plt>
// CHECK-NEXT: bl 0x300000b4 <__AArch64ADRPThunk_absolute>
/// bti_c_target.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: 3000003c: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x0
// CHECK-NEXT: br x16
/// bti_j_target.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x8
// CHECK-NEXT: br x16
/// bti_jc_target.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x10
// CHECK-NEXT: br x16
/// paciasp_target.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x18
// CHECK-NEXT: br x16
/// pacibsp_target.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x20
// CHECK-NEXT: br x16
/// Landing pad for fn2.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x28
// CHECK-NEXT: br x16
/// Landing pad for fn1.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x30
// CHECK-NEXT: br x16
/// Landing pad for fn3.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x3c
// CHECK-NEXT: br x16
/// Landing pad for fn4.
// CHECK-LABEL: <__AArch64ADRPThunk_>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x44
// CHECK-NEXT: br x16
// CHECK-LABEL: <__AArch64ADRPThunk_via_plt>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x80
// CHECK-NEXT: br x16
// CHECK-LABEL: <__AArch64ADRPThunk_absolute>:
// CHECK-NEXT: adrp x16, 0x18001000 <bti_c_target>
// CHECK-NEXT: add x16, x16, #0x98
// CHECK-NEXT: br x16
// CHECK-EXE-LABEL: <long_calls>:
// CHECK-EXE-NEXT: 30000000: bl 0x3000003c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x3000004c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x3000005c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x3000006c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x3000007c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x3000008c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: b 0x3000008c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x3000009c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: b 0x3000009c <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x300000ac <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: b 0x300000ac <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x300000bc <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: b 0x300000bc <__AArch64AbsLongThunk_>
// CHECK-EXE-NEXT: bl 0x300000cc <__AArch64AbsLongThunk_via_plt>
// CHECK-EXE-NEXT: bl 0x300000dc <__AArch64AbsLongThunk_absolute>
// CHECK-EXE-LABEL: 000000003000003c <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 3000003c: ldr x16, 0x30000044 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 00 10 00 18 .word 0x18001000
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 3000004c: ldr x16, 0x30000054 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 08 10 00 18 .word 0x18001008
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 3000005c: ldr x16, 0x30000064 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 10 10 00 18 .word 0x18001010
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 3000006c: ldr x16, 0x30000074 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 18 10 00 18 .word 0x18001018
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 3000007c: ldr x16, 0x30000084 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 20 10 00 18 .word 0x18001020
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 3000008c: ldr x16, 0x30000094 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 28 10 00 18 .word 0x18001028
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 3000009c: ldr x16, 0x300000a4 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 30 10 00 18 .word 0x18001030
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 300000ac: ldr x16, 0x300000b4 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 3c 10 00 18 .word 0x1800103c
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_>:
// CHECK-EXE-NEXT: 300000bc: ldr x16, 0x300000c4 <__AArch64AbsLongThunk_+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 44 10 00 18 .word 0x18001044
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_via_plt>:
// CHECK-EXE-NEXT: 300000cc: ldr x16, 0x300000d4 <__AArch64AbsLongThunk_via_plt+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 80 10 00 18 .word 0x18001080
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
// CHECK-EXE-LABEL: <__AArch64AbsLongThunk_absolute>:
// CHECK-EXE-NEXT: 300000dc: ldr x16, 0x300000e4 <__AArch64AbsLongThunk_absolute+0x8>
// CHECK-EXE-NEXT: br x16
// CHECK-EXE-NEXT: 00 00 00 f0 .word 0xf0000000
// CHECK-EXE-NEXT: 00 00 00 00 .word 0x00000000
//--- lds
PHDRS {
low PT_LOAD FLAGS(0x1 | 0x4);
mid PT_LOAD FLAGS(0x1 | 0x4);
high PT_LOAD FLAGS(0x1 | 0x4);
}
SECTIONS {
.rodata 0x10000000 : { *(.note.gnu.property) } :low
.text_low : { *(.text.0) } :low
.text 0x18001000 : { *(.text.*) } :mid
.plt : { *(.plt) } :mid
.text_high 0x30000000 : { *(.long_calls) } :high
}
//--- shared
.text
.global via_plt
.type via_plt, %function
via_plt:
ret