[PATCH] D41246: [LLD][ELF] Optimize Arm PLT entries

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 15 09:41:42 PST 2017


LGTM
Peter Smith via Phabricator <reviews at reviews.llvm.org> writes:

> peter.smith updated this revision to Diff 127147.
> peter.smith added a comment.
>
> I've implemented the suggestion to choose the form of PLT entry based on whether the offset to the .got.plt can be represented by the shorter encoding. To maintain 16-byte alignment of the entries I've increased the size of the header to 32-bytes. As the --long-plt doesn't do anything any more I've updated all the tests to use the new encoding. Apologies for the size of the diff.
>
>
> https://reviews.llvm.org/D41246
>
> Files:
>   ELF/Arch/ARM.cpp
>   test/ELF/arm-branch-undef-weak-plt-thunk.s
>   test/ELF/arm-exidx-shared.s
>   test/ELF/arm-gnu-ifunc-plt.s
>   test/ELF/arm-gnu-ifunc.s
>   test/ELF/arm-plt-reloc.s
>   test/ELF/arm-thumb-interwork-shared.s
>   test/ELF/arm-thumb-plt-range-thunk-os.s
>   test/ELF/arm-thumb-plt-reloc.s
>   test/ELF/arm-thunk-re-add.s
>
> Index: test/ELF/arm-thunk-re-add.s
> ===================================================================
> --- test/ELF/arm-thunk-re-add.s
> +++ test/ELF/arm-thunk-re-add.s
> @@ -5,7 +5,7 @@
>  // parts we need to speed up the test and avoid a large output file
>  // RUN: llvm-objdump -d %t.so -start-address=16777220 -stop-address=16777244 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
>  // RUN: llvm-objdump -d %t.so -start-address=17825800 -stop-address=17825826 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
> -// RUN: llvm-objdump -d %t.so -start-address=17825824 -stop-address=17825876 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
> +// RUN: llvm-objdump -d %t.so -start-address=17825824 -stop-address=17825892 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
>  
>  // A branch to a Thunk that we create on pass N, can drift out of range if
>  // other Thunks are added in between. In this case we must create a new Thunk
> @@ -65,12 +65,13 @@
>   FUNCTION 30
>   FUNCTION 31
>  // Precreated Thunk Pool goes here
> -// CHECK1:  1000004:       40 f2 24 0c     movw    r12, #36
> +// CHECK1: __ThumbV7PILongThunk_imported:
> +// CHECK1-NEXT:  1000004:       40 f2 30 0c     movw    r12, #48
>  // CHECK1-NEXT:  1000008:       c0 f2 10 0c     movt    r12, #16
>  // CHECK1-NEXT:  100000c:       fc 44   add     r12, pc
>  // CHECK1-NEXT:  100000e:       60 47   bx      r12
>  // CHECK1: __ThumbV7PILongThunk_imported2:
> -// CHECK1-NEXT:  1000010:       40 f2 28 0c     movw    r12, #40
> +// CHECK1-NEXT:  1000010:       40 f2 34 0c     movw    r12, #52
>  // CHECK1-NEXT:  1000014:       c0 f2 10 0c     movt    r12, #16
>  // CHECK1-NEXT:  1000018:       fc 44   add     r12, pc
>  // CHECK1-NEXT:  100001a:       60 47   bx      r12
> @@ -88,7 +89,7 @@
>   beq.w imported
>   b.w imported2
>  // CHECK2: __ThumbV7PILongThunk_imported:
> -// CHECK2-NEXT:  1100008:       40 f2 20 0c     movw    r12, #32
> +// CHECK2-NEXT:  1100008:       40 f2 2c 0c     movw    r12, #44
>  // CHECK2-NEXT:  110000c:       c0 f2 00 0c     movt    r12, #0
>  // CHECK2-NEXT:  1100010:       fc 44   add     r12, pc
>  // CHECK2-NEXT:  1100012:       60 47   bx      r12
> @@ -100,20 +101,23 @@
>  // CHECK3: Disassembly of section .plt:
>  // CHECK3-NEXT: $a:
>  // CHECK3-NEXT:  1100020:       04 e0 2d e5     str     lr, [sp, #-4]!
> -// CHECK3-NEXT:  1100024:       04 e0 9f e5     ldr     lr, [pc, #4]
> -// CHECK3-NEXT:  1100028:       0e e0 8f e0     add     lr, pc, lr
> -// CHECK3-NEXT:  110002c:       08 f0 be e5     ldr     pc, [lr, #8]!
> +// CHECK3-NEXT:  1100024:       00 e6 8f e2     add     lr, pc, #0, #12
> +// CHECK3-NEXT:  1100028:       00 ea 8e e2     add     lr, lr, #0, #20
> +// CHECK3-NEXT:  110002c:       dc ff be e5     ldr     pc, [lr, #4060]!
>  // CHECK3: $d:
> -// CHECK3-NEXT:  1100030:       d0 0f 00 00     .word   0x00000fd0
> +// CHECK3-NEXT:  1100030:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECK3-NEXT:  1100034:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECK3-NEXT:  1100038:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECK3-NEXT:  110003c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // CHECK3: $a:
> -// CHECK3-NEXT:  1100034:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// CHECK3-NEXT:  1100038:       0f c0 8c e0     add     r12, r12, pc
> -// CHECK3-NEXT:  110003c:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECK3-NEXT:  1100040:       00 c6 8f e2     add     r12, pc, #0, #12
> +// CHECK3-NEXT:  1100044:       00 ca 8c e2     add     r12, r12, #0, #20
> +// CHECK3-NEXT:  1100048:       c4 ff bc e5     ldr     pc, [r12, #4036]!
>  // CHECK3: $d:
> -// CHECK3-NEXT:  1100040:       cc 0f 00 00     .word   0x00000fcc
> +// CHECK3-NEXT:  110004c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // CHECK3: $a:
> -// CHECK3-NEXT:  1100044:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// CHECK3-NEXT:  1100048:       0f c0 8c e0     add     r12, r12, pc
> -// CHECK3-NEXT:  110004c:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECK3-NEXT:  1100050:       00 c6 8f e2     add     r12, pc, #0, #12
> +// CHECK3-NEXT:  1100054:       00 ca 8c e2     add     r12, r12, #0, #20
> +// CHECK3-NEXT:  1100058:       b8 ff bc e5     ldr     pc, [r12, #4024]!
>  // CHECK3: $d:
> -// CHECK3-NEXT:  1100050:       c0 0f 00 00     .word   0x00000fc0
> +// CHECK3-NEXT:  110005c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> Index: test/ELF/arm-thumb-plt-reloc.s
> ===================================================================
> --- test/ELF/arm-thumb-plt-reloc.s
> +++ test/ELF/arm-thumb-plt-reloc.s
> @@ -43,50 +43,54 @@
>  // .text is Thumb and .plt is ARM, llvm-objdump can currently only disassemble
>  // as ARM or Thumb. Work around by disassembling twice.
>  // DSOTHUMB: Disassembly of section .text:
> -// DSOTHUMB: func1:
> -// DSOTHUMB-NEXT:    1000:       70 47   bx      lr
> +// DSOTHUMB-NEXT: func1:
> +// DSOTHUMB-NEXT:     1000:     70 47   bx      lr
>  // DSOTHUMB: func2:
> -// DSOTHUMB-NEXT:    1002:       70 47   bx      lr
> +// DSOTHUMB-NEXT:     1002:     70 47   bx      lr
>  // DSOTHUMB: func3:
> -// DSOTHUMB-NEXT:    1004:       70 47   bx      lr
> -// DSOTHUMB-NEXT:    1006:       d4 d4
> +// DSOTHUMB-NEXT:     1004:     70 47   bx      lr
> +// DSOTHUMB-NEXT:     1006:     d4 d4   bmi     #-88
>  // DSOTHUMB: _start:
> -// 0x1008 + 0x28 + 4 = 0x1034 = PLT func1
> -// DSOTHUMB-NEXT:    1008:       00 f0 14 e8     blx     #40
> -// 0x100c + 0x34 + 4 = 0x1044 = PLT func2
> -// DSOTHUMB-NEXT:    100c:       00 f0 1a e8     blx     #52
> -// 0x1010 + 0x40 + 4 = 0x1054 = PLT func3
> -// DSOTHUMB-NEXT:    1010:       00 f0 20 e8     blx     #64
> +// 0x1008 + 0x34 + 4 = 0x1040 = PLT func1
> +// DSOTHUMB-NEXT:     1008:     00 f0 1a e8     blx     #52
> +// 0x100c + 0x40 + 4 = 0x1050 = PLT func2
> +// DSOTHUMB-NEXT:     100c:     00 f0 20 e8     blx     #64
> +// 0x1010 + 0x4C + 4 = 0x1060 = PLT func3
> +// DSOTHUMB-NEXT:     1010:     00 f0 26 e8     blx     #76
>  // DSOARM: Disassembly of section .plt:
>  // DSOARM-NEXT: $a:
> -// DSOARM-NEXT:    1020:       04 e0 2d e5     str     lr, [sp, #-4]!
> -// DSOARM-NEXT:    1024:       04 e0 9f e5     ldr     lr, [pc, #4]
> -// DSOARM-NEXT:    1028:       0e e0 8f e0     add     lr, pc, lr
> -// DSOARM-NEXT:    102c:       08 f0 be e5     ldr     pc, [lr, #8]!
> +// DSOARM-NEXT:     1020:       04 e0 2d e5     str     lr, [sp, #-4]!
> +// (0x1024 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfdc) = 0x2008 = .got.plt[3]
> +// DSOARM-NEXT:     1024:       00 e6 8f e2     add     lr, pc, #0, #12
> +// DSOARM-NEXT:     1028:       00 ea 8e e2     add     lr, lr, #0, #20
> +// DSOARM-NEXT:     102c:       dc ff be e5     ldr     pc, [lr, #4060]!
>  // DSOARM: $d:
> -// DSOARM-NEXT:    1030:       d0 0f 00 00      .word   0x00000fd0
> -// 0x1028 + 8 + 0fd0 = 0x2000
> +
> +// DSOARM-NEXT:     1030:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DSOARM-NEXT:     1034:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DSOARM-NEXT:     1038:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DSOARM-NEXT:     103c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DSOARM: $a:
> -// DSOARM-NEXT:    1034:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DSOARM-NEXT:    1038:       0f c0 8c e0     add     r12, r12, pc
> -// DSOARM-NEXT:    103c:       00 f0 9c e5     ldr     pc, [r12]
> +// (0x1040 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfc4) = 0x200c
> +// DSOARM-NEXT:     1040:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DSOARM-NEXT:     1044:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DSOARM-NEXT:     1048:       c4 ff bc e5     ldr     pc, [r12, #4036]!
>  // DSOARM: $d:
> -// DSOARM-NEXT:    1040:       cc 0f 00 00     .word   0x00000fcc
> -// 0x1038 + 8 + 0fcc = 0x200c
> +// DSOARM-NEXT:     104c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DSOARM: $a:
> -// DSOARM-NEXT:    1044:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DSOARM-NEXT:    1048:       0f c0 8c e0     add     r12, r12, pc
> -// DSOARM-NEXT:    104c:       00 f0 9c e5     ldr     pc, [r12]
> +// (0x1050 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfb8) = 0x2010
> +// DSOARM-NEXT:     1050:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DSOARM-NEXT:     1054:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DSOARM-NEXT:     1058:       b8 ff bc e5     ldr     pc, [r12, #4024]!
>  // DSOARM: $d:
> -// DSOARM-NEXT:    1050:       c0 0f 00 00     .word   0x00000fc0
> -// 0x1048 + 8 + 0fc0 = 0x2010
> +// DSOARM-NEXT:     105c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DSOARM: $a:
> -// DSOARM-NEXT:    1054:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DSOARM-NEXT:    1058:       0f c0 8c e0     add     r12, r12, pc
> -// DSOARM-NEXT:    105c:       00 f0 9c e5     ldr     pc, [r12]
> +// (0x1060 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfac) = 0x2014
> +// DSOARM-NEXT:     1060:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DSOARM-NEXT:     1064:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DSOARM-NEXT:     1068:       ac ff bc e5     ldr     pc, [r12, #4012]!
>  // DSOARM: $d:
> -// DSOARM-NEXT:    1060:       b4 0f 00 00     .word   0x00000fb4
> -// 0x1058 + 8 + 0fb4 = 0x2014
> +// DSOARM-NEXT:     106c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  
>  // DSOREL:    Name: .got.plt
>  // DSOREL-NEXT:    Type: SHT_PROGBITS
> Index: test/ELF/arm-thumb-plt-range-thunk-os.s
> ===================================================================
> --- test/ELF/arm-thumb-plt-range-thunk-os.s
> +++ test/ELF/arm-thumb-plt-range-thunk-os.s
> @@ -6,7 +6,7 @@
>  // RUN: llvm-objdump -d %t.so -start-address=8388608 -stop-address=8388624 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
>  // RUN: llvm-objdump -d %t.so -start-address=16777216 -stop-address=16777256 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
>  // RUN: llvm-objdump -d %t.so -start-address=25165824 -stop-address=25165828 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
> -// RUN: llvm-objdump -d %t.so -start-address=25165828 -stop-address=25165908 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
> +// RUN: llvm-objdump -d %t.so -start-address=25165828 -stop-address=25165924 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
>   .syntax unified
>   .thumb
>  
> @@ -39,50 +39,54 @@
>   .balign 0x0800000
>   bx lr
>  // CHECK2: __ThumbV7PILongThunk_elsewhere:
> -// CHECK2-NEXT:  1000004:       40 f2 14 0c     movw    r12, #20
> +// CHECK2-NEXT:  1000004:       40 f2 20 0c     movw    r12, #32
>  // CHECK2-NEXT:  1000008:       c0 f2 80 0c     movt    r12, #128
>  // CHECK2-NEXT:  100000c:       fc 44   add     r12, pc
>  // CHECK2-NEXT:  100000e:       60 47   bx      r12
>  // CHECK2: __ThumbV7PILongThunk_preemptible:
> -// CHECK2-NEXT:  1000010:       40 f2 18 0c     movw    r12, #24
> +// CHECK2-NEXT:  1000010:       40 f2 24 0c     movw    r12, #36
>  // CHECK2-NEXT:  1000014:       c0 f2 80 0c     movt    r12, #128
>  // CHECK2-NEXT:  1000018:       fc 44   add     r12, pc
>  // CHECK2-NEXT:  100001a:       60 47   bx      r12
>  // CHECK2: __ThumbV7PILongThunk_far_preemptible:
> -// CHECK2-NEXT:  100001c:       40 f2 1c 0c     movw    r12, #28
> +// CHECK2-NEXT:  100001c:       40 f2 28 0c     movw    r12, #40
>  // CHECK2-NEXT:  1000020:       c0 f2 80 0c     movt    r12, #128
>  // CHECK2-NEXT:  1000024:       fc 44   add     r12, pc
>  // CHECK2-NEXT:  1000026:       60 47   bx      r12
> +
>   .section .text.3, "ax", %progbits
>  .balign 0x0800000
>  far_preemptible:
>   bl elsewhere
>  // CHECK3: far_preemptible:
> -// CHECK3:  1800000:       00 f0 10 e8     blx     #32
> +// CHECK3:  1800000:       00 f0 16 e8     blx     #44
>  
>  // CHECK4: Disassembly of section .plt:
>  // CHECK4-NEXT: $a:
> -// CHECK4-NEXT:  1800010:       04 e0 2d e5     str     lr, [sp, #-4]!
> -// CHECK4-NEXT:  1800014:       04 e0 9f e5     ldr     lr, [pc, #4]
> -// CHECK4-NEXT:  1800018:       0e e0 8f e0     add     lr, pc, lr
> -// CHECK4-NEXT:  180001c:       08 f0 be e5     ldr     pc, [lr, #8]!
> +// CHECK4-NEXT:  1800010:	04 e0 2d e5 	str	lr, [sp, #-4]!
> +// CHECK4-NEXT:  1800014:	00 e6 8f e2 	add	lr, pc, #0, #12
> +// CHECK4-NEXT:  1800018:	00 ea 8e e2 	add	lr, lr, #0, #20
> +// CHECK4-NEXT:  180001c:	ec ff be e5 	ldr	pc, [lr, #4076]!
>  // CHECK4: $d:
> -// CHECK4-NEXT:  1800020:       e0 0f 00 00     .word   0x00000fe0
> +// CHECK4-NEXT:  1800020:	d4 d4 d4 d4 	.word	0xd4d4d4d4
> +// CHECK4-NEXT:  1800024:	d4 d4 d4 d4 	.word	0xd4d4d4d4
> +// CHECK4-NEXT:  1800028:	d4 d4 d4 d4 	.word	0xd4d4d4d4
> +// CHECK4-NEXT:  180002c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
>  // CHECK4: $a:
> -// CHECK4-NEXT:  1800024:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// CHECK4-NEXT:  1800028:       0f c0 8c e0     add     r12, r12, pc
> -// CHECK4-NEXT:  180002c:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECK4-NEXT:  1800030:	00 c6 8f e2 	add	r12, pc, #0, #12
> +// CHECK4-NEXT:  1800034:	00 ca 8c e2 	add	r12, r12, #0, #20
> +// CHECK4-NEXT:  1800038:	d4 ff bc e5 	ldr	pc, [r12, #4052]!
>  // CHECK4: $d:
> -// CHECK4-NEXT:  1800030:       dc 0f 00 00     .word   0x00000fdc
> +// CHECK4-NEXT:  180003c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
>  // CHECK4: $a:
> -// CHECK4-NEXT:  1800034:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// CHECK4-NEXT:  1800038:       0f c0 8c e0     add     r12, r12, pc
> -// CHECK4-NEXT:  180003c:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECK4-NEXT:  1800040:	00 c6 8f e2 	add	r12, pc, #0, #12
> +// CHECK4-NEXT:  1800044:	00 ca 8c e2 	add	r12, r12, #0, #20
> +// CHECK4-NEXT:  1800048:	c8 ff bc e5 	ldr	pc, [r12, #4040]!
>  // CHECK4: $d:
> -// CHECK4-NEXT:  1800040:       d0 0f 00 00     .word   0x00000fd0
> +// CHECK4-NEXT:  180004c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
>  // CHECK4: $a:
> -// CHECK4-NEXT:  1800044:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// CHECK4-NEXT:  1800048:       0f c0 8c e0     add     r12, r12, pc
> -// CHECK4-NEXT:  180004c:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECK4-NEXT:  1800050:	00 c6 8f e2 	add	r12, pc, #0, #12
> +// CHECK4-NEXT:  1800054:	00 ca 8c e2 	add	r12, r12, #0, #20
> +// CHECK4-NEXT:  1800058:	bc ff bc e5 	ldr	pc, [r12, #4028]!
>  // CHECK4: $d:
> -// CHECK4-NEXT:  1800050:       c4 0f 00 00     .word   0x00000fc4
> +// CHECK4-NEXT:  180005c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
> Index: test/ELF/arm-thumb-interwork-shared.s
> ===================================================================
> --- test/ELF/arm-thumb-interwork-shared.s
> +++ test/ELF/arm-thumb-interwork-shared.s
> @@ -19,34 +19,37 @@
>  // CHECK-NEXT: 1000: 00 f0 02 b8 b.w #4 <__ThumbV7PILongThunk_elsewhere>
>  // CHECK-NEXT: 1004: 00 f0 06 b8 b.w #12 <__ThumbV7PILongThunk_weakref>
>  // CHECK: __ThumbV7PILongThunk_elsewhere:
> -// CHECK-NEXT:     1008:       40 f2 20 0c     movw    r12, #32
> +// CHECK-NEXT:     1008:       40 f2 2c 0c     movw    r12, #44
>  // CHECK-NEXT:     100c:       c0 f2 00 0c     movt    r12, #0
>  // CHECK-NEXT:     1010:       fc 44   add     r12, pc
>  // CHECK-NEXT:     1012:       60 47   bx      r12
> -
>  // CHECK: __ThumbV7PILongThunk_weakref:
> -// CHECK-NEXT:     1014:       40 f2 24 0c     movw    r12, #36
> +// CHECK-NEXT:     1014:       40 f2 30 0c     movw    r12, #48
>  // CHECK-NEXT:     1018:       c0 f2 00 0c     movt    r12, #0
>  // CHECK-NEXT:     101c:       fc 44   add     r12, pc
>  // CHECK-NEXT:     101e:       60 47   bx      r12
>  
>  // PLT: Disassembly of section .plt:
> -// PLT: $a:
> -// PLT-NEXT:     1020:       04 e0 2d e5     str     lr, [sp, #-4]!
> -// PLT-NEXT:     1024:       04 e0 9f e5     ldr     lr, [pc, #4]
> -// PLT-NEXT:     1028:       0e e0 8f e0     add     lr, pc, lr
> -// PLT-NEXT:     102c:       08 f0 be e5     ldr     pc, [lr, #8]!
> +// PLT-NEXT: $a:
> +// PLT-NEXT:     1020:  04 e0 2d e5     str     lr, [sp, #-4]!
> +// PLT-NEXT:     1024:  00 e6 8f e2     add     lr, pc, #0, #12
> +// PLT-NEXT:     1028:  00 ea 8e e2     add     lr, lr, #0, #20
> +// PLT-NEXT:     102c:  dc ff be e5     ldr     pc, [lr, #4060]!
>  // PLT: $d:
> -// PLT-NEXT:     1030:       d0 0f 00 00     .word   0x00000fd0
> +// PLT-NEXT:     1030:  d4 d4 d4 d4     .word   0xd4d4d4d4
> +// PLT-NEXT:     1034:  d4 d4 d4 d4     .word   0xd4d4d4d4
> +// PLT-NEXT:     1038:  d4 d4 d4 d4     .word   0xd4d4d4d4
> +// PLT-NEXT:     103c:  d4 d4 d4 d4     .word   0xd4d4d4d4
>  // PLT: $a:
> -// PLT-NEXT:     1034:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// PLT-NEXT:     1038:       0f c0 8c e0     add     r12, r12, pc
> -// PLT-NEXT:     103c:       00 f0 9c e5     ldr     pc, [r12]
> +// PLT-NEXT:     1040:  00 c6 8f e2     add     r12, pc, #0, #12
> +// PLT-NEXT:     1044:  00 ca 8c e2     add     r12, r12, #0, #20
> +// PLT-NEXT:     1048:  c4 ff bc e5     ldr     pc, [r12, #4036]!
>  // PLT: $d:
> -// PLT-NEXT:     1040:       cc 0f 00 00     .word   0x00000fcc
> +// PLT-NEXT:     104c:  d4 d4 d4 d4     .word   0xd4d4d4d4
>  // PLT: $a:
> -// PLT-NEXT:     1044:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// PLT-NEXT:     1048:       0f c0 8c e0     add     r12, r12, pc
> -// PLT-NEXT:     104c:       00 f0 9c e5     ldr     pc, [r12]
> +// PLT-NEXT:     1050:  00 c6 8f e2     add     r12, pc, #0, #12
> +// PLT-NEXT:     1054:  00 ca 8c e2     add     r12, r12, #0, #20
> +// PLT-NEXT:     1058:  b8 ff bc e5     ldr     pc, [r12, #4024]!
>  // PLT: $d:
> -// PLT-NEXT:     1050:       c0 0f 00 00     .word   0x00000fc0
> +// PLT-NEXT:     105c:  d4 d4 d4 d4     .word   0xd4d4d4d4
> +
> Index: test/ELF/arm-plt-reloc.s
> ===================================================================
> --- test/ELF/arm-plt-reloc.s
> +++ test/ELF/arm-plt-reloc.s
> @@ -32,51 +32,55 @@
>  // CHECK-NEXT:   11014:        fb ff ff 0a    beq     #-20 <func3>
>  
>  // Expect PLT entries as symbols can be preempted
> +// The .got.plt and .plt displacement is small so we can use small PLT entries.
>  // DSO: Disassembly of section .text:
>  // DSO-NEXT: func1:
> -// DSO-NEXT:    1000:        1e ff 2f e1    bx      lr
> +// DSO-NEXT:     1000:       1e ff 2f e1     bx      lr
>  // DSO: func2:
> -// DSO-NEXT:    1004:        1e ff 2f e1    bx      lr
> +// DSO-NEXT:     1004:       1e ff 2f e1     bx      lr
>  // DSO: func3:
> -// DSO-NEXT:    1008:        1e ff 2f e1    bx      lr
> +// DSO-NEXT:     1008:       1e ff 2f e1     bx      lr
>  // DSO: _start:
> -// S(0x1034) - P(0x100c) + A(-8) = 0x20 = 32
> -// DSO-NEXT:    100c:        08 00 00 ea    b       #32
> -// S(0x1044) - P(0x1010) + A(-8) = 0x2c = 44
> -// DSO-NEXT:    1010:        0b 00 00 eb    bl      #44
> -// S(0x1054) - P(0x1014) + A(-8) = 0x38 = 56
> -// DSO-NEXT:    1014:        0e 00 00 0a    beq     #56
> -
> -// DSO: Disassembly of section .plt:
> +// S(0x1040) - P(0x100c) + A(-8) = 0x2c = 32
> +// DSO-NEXT:     100c:       0b 00 00 ea     b       #44
> +// S(0x1050) - P(0x1010) + A(-8) = 0x38 = 56
> +// DSO-NEXT:     1010:       0e 00 00 eb     bl      #56
> +// S(0x10160) - P(0x1014) + A(-8) = 0x44 = 68
> +// DSO-NEXT:     1014:       11 00 00 0a     beq     #68
> +// DSO-NEXT: Disassembly of section .plt:
>  // DSO-NEXT: $a:
>  // DSO-NEXT:     1020:       04 e0 2d e5     str     lr, [sp, #-4]!
> -// DSO-NEXT:     1024:       04 e0 9f e5     ldr     lr, [pc, #4]
> -// DSO-NEXT:     1028:       0e e0 8f e0     add     lr, pc, lr
> -// DSO-NEXT:     102c:       08 f0 be e5     ldr     pc, [lr, #8]!
> -// 0x1028 + 8 + 0fd0 = 0x2000
> +// (0x1024 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfdc) = 0x2008 = .got.plt[3]
> +// DSO-NEXT:     1024:       00 e6 8f e2     add     lr, pc, #0, #12
> +// DSO-NEXT:     1028:       00 ea 8e e2     add     lr, lr, #0, #20
> +// DSO-NEXT:     102c:       dc ff be e5     ldr     pc, [lr, #4060]!
>  // DSO: $d:
> -// DSO-NEXT:     1030:       d0 0f 00 00     .word   0x00000fd0
> +// DSO-NEXT:     1030:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DSO-NEXT:     1034:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DSO-NEXT:     1038:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DSO-NEXT:     103c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DSO: $a:
> -// DSO-NEXT:     1034:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DSO-NEXT:     1038:       0f c0 8c e0     add     r12, r12, pc
> -// DSO-NEXT:     103c:       00 f0 9c e5     ldr     pc, [r12]
> -// 0x1038 + 8 + 0fcc = 0x200c
> +// (0x1040 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfc4) = 0x200c
> +// DSO-NEXT:     1040:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DSO-NEXT:     1044:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DSO-NEXT:     1048:       c4 ff bc e5     ldr     pc, [r12, #4036]!
>  // DSO: $d:
> -// DSO-NEXT:     1040:       cc 0f 00 00     .word   0x00000fcc
> +// DSO-NEXT:     104c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DSO: $a:
> -// DSO-NEXT:     1044:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DSO-NEXT:     1048:       0f c0 8c e0     add     r12, r12, pc
> -// DSO-NEXT:     104c:       00 f0 9c e5     ldr     pc, [r12]
> -// 0x1048 + 8 + 0fc0 = 0x2010
> +// (0x1050 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfb8) = 0x2010
> +// DSO-NEXT:     1050:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DSO-NEXT:     1054:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DSO-NEXT:     1058:       b8 ff bc e5     ldr     pc, [r12, #4024]!
>  // DSO: $d:
> -// DSO-NEXT:     1050:       c0 0f 00 00     .word   0x00000fc0
> +// DSO-NEXT:     105c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DSO: $a:
> -// DSO-NEXT:     1054:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DSO-NEXT:     1058:       0f c0 8c e0     add     r12, r12, pc
> -// DSO-NEXT:     105c:       00 f0 9c e5     ldr     pc, [r12]
> -// 0x1058 + 8 + 0fb4 = 0x2014
> +// (0x1060 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfac) = 0x2014
> +// DSO-NEXT:     1060:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DSO-NEXT:     1064:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DSO-NEXT:     1068:       ac ff bc e5     ldr     pc, [r12, #4012]!
>  // DSO: $d:
> -// DSO-NEXT:     1060:       b4 0f 00 00     .word   0x00000fb4
> +// DSO-NEXT:     106c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +
>  
>  // DSOREL:    Name: .got.plt
>  // DSOREL-NEXT:    Type: SHT_PROGBITS
> @@ -96,3 +100,199 @@
>  // DSOREL-NEXT:    0x200C R_ARM_JUMP_SLOT func1 0x0
>  // DSOREL-NEXT:    0x2010 R_ARM_JUMP_SLOT func2 0x0
>  // DSOREL-NEXT:    0x2014 R_ARM_JUMP_SLOT func3 0x0
> +
> +// Test a large separation between the .plt and .got.plt
> +// The .got.plt and .plt displacement is large but still within the range
> +// of the short plt sequence.
> +// RUN: echo "SECTIONS { \
> +// RUN:       .text 0x1000 : { *(.text) } \
> +// RUN:       .plt  0x2000 : { *(.plt) *(.plt.*) } \
> +// RUN:       .got.plt 0x1100000 : { *(.got.plt) } \
> +// RUN:       }" > %t.script
> +// RUN: ld.lld --hash-style=sysv --script %t.script -shared %t1 %t2 -o %t4
> +// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t4 | FileCheck --check-prefix=CHECKHIGH %s
> +// RUN: llvm-readobj -s -r %t4 | FileCheck --check-prefix=DSORELHIGH %s
> +
> +// CHECKHIGH: Disassembly of section .text:
> +// CHECKHIGH-NEXT: func1:
> +// CHECKHIGH-NEXT:     1000:       1e ff 2f e1     bx      lr
> +// CHECKHIGH: func2:
> +// CHECKHIGH-NEXT:     1004:       1e ff 2f e1     bx      lr
> +// CHECKHIGH: func3:
> +// CHECKHIGH-NEXT:     1008:       1e ff 2f e1     bx      lr
> +// CHECKHIGH: _start:
> +// CHECKHIGH-NEXT:     100c:       03 04 00 ea     b       #4108 <$a>
> +// CHECKHIGH-NEXT:     1010:       06 04 00 eb     bl      #4120 <$a>
> +// CHECKHIGH-NEXT:     1014:       09 04 00 0a     beq     #4132 <$a>
> +// CHECKHIGH-NEXT: Disassembly of section .plt:
> +// CHECKHIGH-NEXT: $a:
> +// CHECKHIGH-NEXT:     2000:       04 e0 2d e5     str     lr, [sp, #-4]!
> +// CHECKHIGH-NEXT:     2004:       10 e6 8f e2     add     lr, pc, #16, #12
> +// CHECKHIGH-NEXT:     2008:       fd ea 8e e2     add     lr, lr, #1036288
> +// CHECKHIGH-NEXT:     200c:       fc ff be e5     ldr     pc, [lr, #4092]!
> +// CHECKHIGH: $d:
> +// CHECKHIGH-NEXT:     2010:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKHIGH-NEXT:     2014:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKHIGH-NEXT:     2018:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKHIGH-NEXT:     201c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKHIGH: $a:
> +// CHECKHIGH-NEXT:     2020:       10 c6 8f e2     add     r12, pc, #16, #12
> +// CHECKHIGH-NEXT:     2024:       fd ca 8c e2     add     r12, r12, #1036288
> +// CHECKHIGH-NEXT:     2028:       e4 ff bc e5     ldr     pc, [r12, #4068]!
> +// CHECKHIGH: $d:
> +// CHECKHIGH-NEXT:     202c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKHIGH: $a:
> +// CHECKHIGH-NEXT:     2030:       10 c6 8f e2     add     r12, pc, #16, #12
> +// CHECKHIGH-NEXT:     2034:       fd ca 8c e2     add     r12, r12, #1036288
> +// CHECKHIGH-NEXT:     2038:       d8 ff bc e5     ldr     pc, [r12, #4056]!
> +// CHECKHIGH: $d:
> +// CHECKHIGH-NEXT:     203c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKHIGH: $a:
> +// CHECKHIGH-NEXT:     2040:       10 c6 8f e2     add     r12, pc, #16, #12
> +// CHECKHIGH-NEXT:     2044:       fd ca 8c e2     add     r12, r12, #1036288
> +// CHECKHIGH-NEXT:     2048:       cc ff bc e5     ldr     pc, [r12, #4044]!
> +// CHECKHIGH: $d:
> +// CHECKHIGH-NEXT:     204c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +
> +// DSORELHIGH:     Name: .got.plt
> +// DSORELHIGH-NEXT:     Type: SHT_PROGBITS
> +// DSORELHIGH-NEXT:     Flags [
> +// DSORELHIGH-NEXT:       SHF_ALLOC
> +// DSORELHIGH-NEXT:       SHF_WRITE
> +// DSORELHIGH-NEXT:     ]
> +// DSORELHIGH-NEXT:     Address: 0x1100000
> +// DSORELHIGH: Relocations [
> +// DSORELHIGH-NEXT:   Section (6) .rel.plt {
> +// DSORELHIGH-NEXT:     0x110000C R_ARM_JUMP_SLOT func1 0x0
> +// DSORELHIGH-NEXT:     0x1100010 R_ARM_JUMP_SLOT func2 0x0
> +// DSORELHIGH-NEXT:     0x1100014 R_ARM_JUMP_SLOT func3 0x0
> +
> +// Test a very large separation between the .plt and .got.plt so we must use
> +// large plt entries that do not have any range restriction.
> +// RUN: echo "SECTIONS { \
> +// RUN:       .text 0x1000 : { *(.text) } \
> +// RUN:       .plt  0x2000 : { *(.plt) *(.plt.*) } \
> +// RUN:       .got.plt 0x11111100 : { *(.got.plt) } \
> +// RUN:       }" > %t2.script
> +// RUN: ld.lld --hash-style=sysv --script %t2.script -shared %t1 %t2 -o %t5
> +// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t5 | FileCheck --check-prefix=CHECKLONG %s
> +// RUN: llvm-readobj -s -r %t5 | FileCheck --check-prefix=DSORELLONG %s
> +
> +// CHECKLONG: Disassembly of section .text:
> +// CHECKLONG-NEXT: func1:
> +// CHECKLONG-NEXT:     1000:       1e ff 2f e1     bx      lr
> +// CHECKLONG: func2:
> +// CHECKLONG-NEXT:     1004:       1e ff 2f e1     bx      lr
> +// CHECKLONG: func3:
> +// CHECKLONG-NEXT:     1008:       1e ff 2f e1     bx      lr
> +// CHECKLONG: _start:
> +// CHECKLONG-NEXT:     100c:       03 04 00 ea     b       #4108 <$a>
> +// CHECKLONG-NEXT:     1010:       06 04 00 eb     bl      #4120 <$a>
> +// CHECKLONG-NEXT:     1014:       09 04 00 0a     beq     #4132 <$a>
> +// CHECKLONG-NEXT: Disassembly of section .plt:
> +// CHECKLONG-NEXT: $a:
> +// CHECKLONG-NEXT:     2000:       04 e0 2d e5     str     lr, [sp, #-4]!
> +// CHECKLONG-NEXT:     2004:       04 e0 9f e5     ldr     lr, [pc, #4]
> +// CHECKLONG-NEXT:     2008:       0e e0 8f e0     add     lr, pc, lr
> +// CHECKLONG-NEXT:     200c:       08 f0 be e5     ldr     pc, [lr, #8]!
> +// CHECKLONG: $d:
> +// CHECKLONG-NEXT:     2010:       f0 f0 10 11     .word   0x1110f0f0
> +// CHECKLONG-NEXT:     2014:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKLONG-NEXT:     2018:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKLONG-NEXT:     201c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKLONG: $a:
> +// CHECKLONG-NEXT:     2020:       04 c0 9f e5     ldr     r12, [pc, #4]
> +// CHECKLONG-NEXT:     2024:       0f c0 8c e0     add     r12, r12, pc
> +// CHECKLONG-NEXT:     2028:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECKLONG: $d:
> +// CHECKLONG-NEXT:     202c:       e0 f0 10 11     .word   0x1110f0e0
> +// CHECKLONG: $a:
> +// CHECKLONG-NEXT:     2030:       04 c0 9f e5     ldr     r12, [pc, #4]
> +// CHECKLONG-NEXT:     2034:       0f c0 8c e0     add     r12, r12, pc
> +// CHECKLONG-NEXT:     2038:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECKLONG: $d:
> +// CHECKLONG-NEXT:     203c:       d4 f0 10 11     .word   0x1110f0d4
> +// CHECKLONG: $a:
> +// CHECKLONG-NEXT:     2040:       04 c0 9f e5     ldr     r12, [pc, #4]
> +// CHECKLONG-NEXT:     2044:       0f c0 8c e0     add     r12, r12, pc
> +// CHECKLONG-NEXT:     2048:       00 f0 9c e5     ldr     pc, [r12]
> +// CHECKLONG: $d:
> +// CHECKLONG-NEXT:     204c:       c8 f0 10 11     .word   0x1110f0c8
> +
> +// DSORELLONG: Name: .got.plt
> +// DSORELLONG-NEXT:     Type: SHT_PROGBITS
> +// DSORELLONG-NEXT:     Flags [
> +// DSORELLONG-NEXT:       SHF_ALLOC
> +// DSORELLONG-NEXT:       SHF_WRITE
> +// DSORELLONG-NEXT:     ]
> +// DSORELLONG-NEXT:     Address: 0x11111100
> +// DSORELLONG: Relocations [
> +// DSORELLONG-NEXT:   Section (6) .rel.plt {
> +// DSORELLONG-NEXT:     0x1111110C R_ARM_JUMP_SLOT func1 0x0
> +// DSORELLONG-NEXT:     0x11111110 R_ARM_JUMP_SLOT func2 0x0
> +// DSORELLONG-NEXT:     0x11111114 R_ARM_JUMP_SLOT func3 0x0
> +
> +// Test a separation between the .plt and .got.plt that is part in range of
> +// short table entries and part needing long entries. We use the long entries
> +// only when we need to.
> +// RUN: echo "SECTIONS { \
> +// RUN:       .text 0x1000 : { *(.text) } \
> +// RUN:       .plt  0x2000 : { *(.plt) *(.plt.*) } \
> +// RUN:       .got.plt 0x8002020 : { *(.got.plt) } \
> +// RUN:       }" > %t3.script
> +// RUN: ld.lld --hash-style=sysv --script %t3.script -shared %t1 %t2 -o %t6
> +// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t6 | FileCheck --check-prefix=CHECKMIX %s
> +// RUN: llvm-readobj -s -r %t6 | FileCheck --check-prefix=DSORELMIX %s
> +
> +// CHECKMIX: Disassembly of section .text:
> +// CHECKMIX-NEXT: func1:
> +// CHECKMIX-NEXT:     1000:     1e ff 2f e1     bx      lr
> +// CHECKMIX: func2:
> +// CHECKMIX-NEXT:     1004:     1e ff 2f e1     bx      lr
> +// CHECKMIX: func3:
> +// CHECKMIX-NEXT:     1008:     1e ff 2f e1     bx      lr
> +// CHECKMIX: _start:
> +// CHECKMIX-NEXT:     100c:     03 04 00 ea     b       #4108 <$a>
> +// CHECKMIX-NEXT:     1010:     06 04 00 eb     bl      #4120 <$a>
> +// CHECKMIX-NEXT:     1014:     09 04 00 0a     beq     #4132 <$a>
> +// CHECKMIX-NEXT: Disassembly of section .plt:
> +// CHECKMIX-NEXT: $a:
> +// CHECKMIX-NEXT:     2000:     04 e0 2d e5     str     lr, [sp, #-4]!
> +// CHECKMIX-NEXT:     2004:     04 e0 9f e5     ldr     lr, [pc, #4]
> +// CHECKMIX-NEXT:     2008:     0e e0 8f e0     add     lr, pc, lr
> +// CHECKMIX-NEXT:     200c:     08 f0 be e5     ldr     pc, [lr, #8]!
> +// CHECKMIX: $d:
> +// CHECKMIX-NEXT:     2010:     10 00 00 08     .word   0x08000010
> +// CHECKMIX-NEXT:     2014:     d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKMIX-NEXT:     2018:     d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKMIX-NEXT:     201c:     d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKMIX: $a:
> +// CHECKMIX-NEXT:     2020:     04 c0 9f e5     ldr     r12, [pc, #4]
> +// CHECKMIX-NEXT:     2024:     0f c0 8c e0     add     r12, r12, pc
> +// CHECKMIX-NEXT:     2028:     00 f0 9c e5     ldr     pc, [r12]
> +// CHECKMIX: $d:
> +// CHECKMIX-NEXT:     202c:     00 00 00 08     .word   0x08000000
> +// CHECKMIX: $a:
> +// CHECKMIX-NEXT:     2030:     7f c6 8f e2     add     r12, pc, #133169152
> +// CHECKMIX-NEXT:     2034:     ff ca 8c e2     add     r12, r12, #1044480
> +// CHECKMIX-NEXT:     2038:     f8 ff bc e5     ldr     pc, [r12, #4088]!
> +// CHECKMIX: $d:
> +// CHECKMIX-NEXT:     203c:     d4 d4 d4 d4     .word   0xd4d4d4d4
> +// CHECKMIX: $a:
> +// CHECKMIX-NEXT:     2040:     7f c6 8f e2     add     r12, pc, #133169152
> +// CHECKMIX-NEXT:     2044:     ff ca 8c e2     add     r12, r12, #1044480
> +// CHECKMIX-NEXT:     2048:     ec ff bc e5     ldr     pc, [r12, #4076]!
> +// CHECKMIX: $d:
> +// CHECKMIX-NEXT:     204c:     d4 d4 d4 d4     .word   0xd4d4d4d4
> +
> +// DSORELMIX:    Name: .got.plt
> +// DSORELMIX-NEXT:     Type: SHT_PROGBITS
> +// DSORELMIX-NEXT:     Flags [
> +// DSORELMIX-NEXT:       SHF_ALLOC
> +// DSORELMIX-NEXT:       SHF_WRITE
> +// DSORELMIX-NEXT:     ]
> +// DSORELMIX-NEXT:     Address: 0x8002020
> +// DSORELMIX:   Section (6) .rel.plt {
> +// DSORELMIX-NEXT:     0x800202C R_ARM_JUMP_SLOT func1 0x0
> +// DSORELMIX-NEXT:     0x8002030 R_ARM_JUMP_SLOT func2 0x0
> +// DSORELMIX-NEXT:     0x8002034 R_ARM_JUMP_SLOT func3 0x0
> Index: test/ELF/arm-gnu-ifunc.s
> ===================================================================
> --- test/ELF/arm-gnu-ifunc.s
> +++ test/ELF/arm-gnu-ifunc.s
> @@ -111,30 +111,29 @@
>  
>  // DISASM: Disassembly of section .text:
>  // DISASM-NEXT: foo:
> -// DISASM-NEXT:    11000:	1e ff 2f e1 	bx	lr
> -// DISASM:      bar:
> -// DISASM-NEXT:    11004:	1e ff 2f e1 	bx	lr
> -// DISASM:       _start:
> -// DISASM-NEXT:    11008:	04 00 00 eb 	bl	#16
> -// DISASM-NEXT:    1100c:	07 00 00 eb 	bl	#28
> +// DISASM-NEXT:    11000:      1e ff 2f e1     bx      lr
> +// DISASM: bar:
> +// DISASM-NEXT:    11004:      1e ff 2f e1     bx      lr
> +// DISASM: _start:
> +// DISASM-NEXT:    11008:      04 00 00 eb     bl      #16
> +// DISASM-NEXT:    1100c:      07 00 00 eb     bl      #28
>  // 1 * 65536 + 244 = 0x100f4 __rel_iplt_start
> -// DISASM-NEXT:    11010:	f4 00 00 e3 	movw	r0, #244
> -// DISASM-NEXT:    11014:	01 00 40 e3 	movt	r0, #1
> +// DISASM-NEXT:    11010:      f4 00 00 e3     movw    r0, #244
> +// DISASM-NEXT:    11014:      01 00 40 e3     movt    r0, #1
>  // 1 * 65536 + 260 = 0x10104 __rel_iplt_end
> -// DISASM-NEXT:    11018:	04 01 00 e3 	movw	r0, #260
> -// DISASM-NEXT:    1101c:	01 00 40 e3 	movt	r0, #1
> +// DISASM-NEXT:    11018:      04 01 00 e3     movw    r0, #260
> +// DISASM-NEXT:    1101c:      01 00 40 e3     movt    r0, #1
>  // DISASM-NEXT: Disassembly of section .plt:
> -// DISASM: $a:
> -// DISASM-NEXT:    11020:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DISASM-NEXT:    11024:       0f c0 8c e0     add     r12, r12, pc
> -// 11024 + 8 + fd4 = 0x12000
> -// DISASM-NEXT:    11028:       00 f0 9c e5     ldr     pc, [r12]
> +// DISASM-NEXT: $a:
> +// DISASM-NEXT:    11020:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DISASM-NEXT:    11024:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DISASM-NEXT:    11028:       d8 ff bc e5     ldr     pc, [r12, #4056]!
>  // DISASM: $d:
> -// DISASM-NEXT:    1102c:       d4 0f 00 00     .word   0x00000fd4
> +// DISASM-NEXT:    1102c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DISASM: $a:
> -// DISASM-NEXT:    11030:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DISASM-NEXT:    11034:       0f c0 8c e0     add     r12, r12, pc
> -// 11034 + 8 + fc8 = 0x12004
> -// DISASM-NEXT:    11038:       00 f0 9c e5     ldr     pc, [r12]
> +// DISASM-NEXT:    11030:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DISASM-NEXT:    11034:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DISASM-NEXT:    11038:       cc ff bc e5     ldr     pc, [r12, #4044]!
>  // DISASM: $d:
> -// DISASM-NEXT:    1103c:       c8 0f 00 00     .word   0x00000fc8
> +// DISASM-NEXT:    1103c:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +
> Index: test/ELF/arm-gnu-ifunc-plt.s
> ===================================================================
> --- test/ELF/arm-gnu-ifunc-plt.s
> +++ test/ELF/arm-gnu-ifunc-plt.s
> @@ -33,49 +33,49 @@
>  // DISASM-NEXT:    11000:       1e ff 2f e1     bx      lr
>  // DISASM: bar:
>  // DISASM-NEXT:    11004:       1e ff 2f e1     bx      lr
> -// DISASM:      _start:
> +// DISASM: _start:
>  // DISASM-NEXT:    11008:       14 00 00 eb     bl      #80
>  // DISASM-NEXT:    1100c:       17 00 00 eb     bl      #92
> -// DISASM:         11010:       00 00 00 00     .word   0x00000000
> +// DISASM: $d.1:
> +// DISASM-NEXT:    11010:       00 00 00 00     .word   0x00000000
>  // DISASM-NEXT:    11014:       04 00 00 00     .word   0x00000004
> -// DISASM:         11018:       05 00 00 eb     bl      #20
> -// DISASM-NEXT:    1101c:       08 00 00 eb     bl      #32
> +// DISASM:         11018:       08 00 00 eb     bl      #32
> +// DISASM-NEXT:    1101c:       0b 00 00 eb     bl      #44
>  // DISASM-NEXT: Disassembly of section .plt:
>  // DISASM-NEXT: $a:
>  // DISASM-NEXT:    11020:       04 e0 2d e5     str     lr, [sp, #-4]!
> -// DISASM-NEXT:    11024:       04 e0 9f e5     ldr     lr, [pc, #4]
> -// DISASM-NEXT:    11028:       0e e0 8f e0     add     lr, pc, lr
> -// DISASM-NEXT:    1102c:       08 f0 be e5     ldr     pc, [lr, #8]!
> +// DISASM-NEXT:    11024:       00 e6 8f e2     add     lr, pc, #0, #12
> +// DISASM-NEXT:    11028:       00 ea 8e e2     add     lr, lr, #0, #20
> +// DISASM-NEXT:    1102c:       dc ff be e5     ldr     pc, [lr, #4060]!
>  // DISASM: $d:
> -// DISASM-NEXT:    11030:       d0 0f 00 00     .word   0x00000fd0
> +// DISASM-NEXT:    11030:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DISASM-NEXT:    11034:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DISASM-NEXT:    11038:       d4 d4 d4 d4     .word   0xd4d4d4d4
> +// DISASM-NEXT:    1103c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DISASM: $a:
> -// DISASM-NEXT:    11034:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DISASM-NEXT:    11038:       0f c0 8c e0     add     r12, r12, pc
> -// DISASM-NEXT:    1103c:       00 f0 9c e5     ldr     pc, [r12]
> +// DISASM-NEXT:    11040:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DISASM-NEXT:    11044:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DISASM-NEXT:    11048:       c4 ff bc e5     ldr     pc, [r12, #4036]!
>  // DISASM: $d:
> -// DISASM-NEXT:    11040:       cc 0f 00 00     .word   0x00000fcc
> +// DISASM-NEXT:    1104c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DISASM: $a:
> -// DISASM-NEXT:    11044:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DISASM-NEXT:    11048:       0f c0 8c e0     add     r12, r12, pc
> -// DISASM-NEXT:    1104c:       00 f0 9c e5     ldr     pc, [r12]
> +// DISASM-NEXT:    11050:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DISASM-NEXT:    11054:       00 ca 8c e2     add     r12, r12, #0, #20
> +// DISASM-NEXT:    11058:       b8 ff bc e5     ldr     pc, [r12, #4024]!
>  // DISASM: $d:
> -// DISASM-NEXT:    11050:       c0 0f 00 00     .word   0x00000fc0
> -// Alignment to 16 byte boundary not strictly necessary on ARM, but harmless
> -// DISASM-NEXT:    11054:       d4 d4 d4 d4     .word   0xd4d4d4d4
> -// DISASM-NEXT:    11058:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DISASM-NEXT:    1105c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DISASM: $a:
> -// DISASM-NEXT:    11060:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DISASM-NEXT:    11064:       0f c0 8c e0     add     r12, r12, pc
> -// DISASM-NEXT:    11068:       00 f0 9c e5     ldr     pc, [r12]
> +// DISASM-NEXT:    11060:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DISASM-NEXT:    11064:       02 ca 8c e2     add     r12, r12, #8192
> +// DISASM-NEXT:    11068:       18 f0 bc e5     ldr     pc, [r12, #24]!
>  // DISASM: $d:
> -// DISASM-NEXT:    1106c:       14 20 00 00     .word   0x00002014
> +// DISASM-NEXT:    1106c:       d4 d4 d4 d4     .word   0xd4d4d4d4
>  // DISASM: $a:
> -// DISASM-NEXT:    11070:       04 c0 9f e5     ldr     r12, [pc, #4]
> -// DISASM-NEXT:    11074:       0f c0 8c e0     add     r12, r12, pc
> -// DISASM-NEXT:    11078:       00 f0 9c e5     ldr     pc, [r12]
> +// DISASM-NEXT:    11070:       00 c6 8f e2     add     r12, pc, #0, #12
> +// DISASM-NEXT:    11074:       02 ca 8c e2     add     r12, r12, #8192
> +// DISASM-NEXT:    11078:       0c f0 bc e5     ldr     pc, [r12, #12]!
>  // DISASM: $d:
> -// DISASM-NEXT:    1107c:       08 20 00 00     .word   0x00002008
> +// DISASM-NEXT:   1107c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
>  
>  .syntax unified
>  .text
> Index: test/ELF/arm-exidx-shared.s
> ===================================================================
> --- test/ELF/arm-exidx-shared.s
> +++ test/ELF/arm-exidx-shared.s
> @@ -41,5 +41,5 @@
>  // CHECK-NEXT:     0x200C R_ARM_JUMP_SLOT __gxx_personality_v0
>  
>  // CHECK-EXTAB: Contents of section .ARM.extab:
> -// 014c + 0ed8 = 0x1024 = __gxx_personality_v0(PLT)
> -// CHECK-EXTAB-NEXT:  014c d80e0000 b0b0b000 00000000
> +// 014c + 0ee4 = 0x1030 = __gxx_personality_v0(PLT)
> +// CHECK-EXTAB-NEXT:  014c e40e0000 b0b0b000 00000000
> Index: test/ELF/arm-branch-undef-weak-plt-thunk.s
> ===================================================================
> --- test/ELF/arm-branch-undef-weak-plt-thunk.s
> +++ test/ELF/arm-branch-undef-weak-plt-thunk.s
> @@ -26,10 +26,10 @@
>  // CHECK-NEXT:    11000:       00 00 00 ea     b       #0 <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for>
>  // CHECK-NEXT:    11004:       02 00 00 eb     bl      #8 <__ARMv7ABSLongThunk_bar2>
>  // CHECK: __ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for:
> -// CHECK-NEXT:    11008:       34 c0 01 e3     movw    r12, #4148
> -// CHECK-NEXT:    1100c:       01 c2 40 e3     movt    r12, #513
> -// CHECK-NEXT:    11010:       1c ff 2f e1     bx      r12
> +// CHECK-NEXT:    11008:        40 c0 01 e3     movw    r12, #4160
> +// CHECK-NEXT:    1100c:        01 c2 40 e3     movt    r12, #513
> +// CHECK-NEXT:    11010:        1c ff 2f e1     bx      r12
>  // CHECK: __ARMv7ABSLongThunk_bar2:
> -// CHECK-NEXT:    11014:       44 c0 01 e3     movw    r12, #4164
> -// CHECK-NEXT:    11018:       01 c2 40 e3     movt    r12, #513
> -// CHECK-NEXT:    1101c:       1c ff 2f e1     bx      r12
> +// CHECK-NEXT:    11014:        50 c0 01 e3     movw    r12, #4176
> +// CHECK-NEXT:    11018:        01 c2 40 e3     movt    r12, #513
> +// CHECK-NEXT:    1101c:        1c ff 2f e1     bx      r12
> Index: ELF/Arch/ARM.cpp
> ===================================================================
> --- ELF/Arch/ARM.cpp
> +++ ELF/Arch/ARM.cpp
> @@ -58,7 +58,7 @@
>    GotEntrySize = 4;
>    GotPltEntrySize = 4;
>    PltEntrySize = 16;
> -  PltHeaderSize = 20;
> +  PltHeaderSize = 32;
>    TrapInstr = 0xd4d4d4d4;
>    // ARM uses Variant 1 TLS
>    TcbSize = 8;
> @@ -184,32 +184,65 @@
>    write32le(Buf, S.getVA());
>  }
>  
> -void ARM::writePltHeader(uint8_t *Buf) const {
> +// Long form PLT Heade that does not have any restrictions on the displacement
> +// of the .plt from the .plt.got.
> +static void writePltHeaderLong(uint8_t *Buf) {
>    const uint8_t PltData[] = {
>        0x04, 0xe0, 0x2d, 0xe5, //     str lr, [sp,#-4]!
>        0x04, 0xe0, 0x9f, 0xe5, //     ldr lr, L2
>        0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr
>        0x08, 0xf0, 0xbe, 0xe5, //     ldr pc, [lr, #8]
>        0x00, 0x00, 0x00, 0x00, // L2: .word   &(.got.plt) - L1 - 8
> -  };
> +      0xd4, 0xd4, 0xd4, 0xd4, //     Pad to 32-byte boundary
> +      0xd4, 0xd4, 0xd4, 0xd4, //     Pad to 32-byte boundary
> +      0xd4, 0xd4, 0xd4, 0xd4};
>    memcpy(Buf, PltData, sizeof(PltData));
>    uint64_t GotPlt = InX::GotPlt->getVA();
>    uint64_t L1 = InX::Plt->getVA() + 8;
>    write32le(Buf + 16, GotPlt - L1 - 8);
>  }
>  
> +// The default PLT header requires the .plt.got to be within 128 Mb of the
> +// .plt in the positive direction.
> +void ARM::writePltHeader(uint8_t *Buf) const {
> +  // Use a similar sequence to that in writePlt(), the difference is the calling
> +  // conventions mean we use lr instead of ip. The PLT entry is responsible for
> +  // saving lr on the stack, the dynamic loader is responsible for reloading
> +  // it.
> +  const uint32_t PltData[] = {
> +      0xe52de004, // L1: str lr, [sp,#-4]!
> +      0xe28fe600, //     add lr, pc,  #0x0NN00000 &(.got.plt - L1 - 4)
> +      0xe28eea00, //     add lr, lr,  #0x000NN000 &(.got.plt - L1 - 4)
> +      0xe5bef000, //     ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4)
> +  };
> +
> +  uint64_t Offset = InX::GotPlt->getVA() - InX::Plt->getVA() - 4;
> +  if (!llvm::isUInt<27>(Offset)) {
> +    // We cannot encode the Offset, use the long form.
> +    writePltHeaderLong(Buf);
> +    return;
> +  }
> +  write32le(Buf + 0, PltData[0]);
> +  write32le(Buf + 4, PltData[1] | ((Offset >> 20) & 0xff));
> +  write32le(Buf + 8, PltData[2] | ((Offset >> 12) & 0xff));
> +  write32le(Buf + 12, PltData[3] | (Offset & 0xfff));
> +  write32le(Buf + 16, TrapInstr); // Pad to 32-byte boundary
> +  write32le(Buf + 20, TrapInstr);
> +  write32le(Buf + 24, TrapInstr);
> +  write32le(Buf + 28, TrapInstr);
> +}
> +
>  void ARM::addPltHeaderSymbols(InputSectionBase *ISD) const {
>    auto *IS = cast<InputSection>(ISD);
>    addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS);
>    addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS);
>  }
>  
> -void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
> -                   uint64_t PltEntryAddr, int32_t Index,
> -                   unsigned RelOff) const {
> -  // FIXME: Using simple code sequence with simple relocations.
> -  // There is a more optimal sequence but it requires support for the group
> -  // relocations. See ELF for the ARM Architecture Appendix A.3
> +// Long form PLT entries that do not have any restrictions on the displacement
> +// of the .plt from the .plt.got.
> +static void writePltLong(uint8_t *Buf, uint64_t GotPltEntryAddr,
> +                         uint64_t PltEntryAddr, int32_t Index,
> +                         unsigned RelOff) {
>    const uint8_t PltData[] = {
>        0x04, 0xc0, 0x9f, 0xe5, //     ldr ip, L2
>        0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
> @@ -221,6 +254,34 @@
>    write32le(Buf + 12, GotPltEntryAddr - L1 - 8);
>  }
>  
> +// The default PLT entries require the .plt.got to be within 128 Mb of the
> +// .plt in the positive direction.
> +void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
> +                   uint64_t PltEntryAddr, int32_t Index,
> +                   unsigned RelOff) const {
> +  // The PLT entry is similar to the example given in Appendix A of ELF for
> +  // the Arm Architecture. Instead of using the Group Relocations to find the
> +  // optimal rotation for the 8-bit immediate used in the add instructions we
> +  // hard code the most compact rotations for simplicity. This saves a load
> +  // instruction over the long plt sequences.
> +  const uint32_t PltData[] = {
> +      0xe28fc600, // L1: add ip, pc,  #0x0NN00000  Offset(&(.plt.got) - L1 - 8
> +      0xe28cca00, //     add ip, ip,  #0x000NN000  Offset(&(.plt.got) - L1 - 8
> +      0xe5bcf000, //     ldr pc, [ip, #0x00000NNN] Offset(&(.plt.got) - L1 - 8
> +  };
> +
> +  uint64_t Offset = GotPltEntryAddr - PltEntryAddr - 8;
> +  if (!llvm::isUInt<27>(Offset)) {
> +    // We cannot encode the Offset, use the long form.
> +    writePltLong(Buf, GotPltEntryAddr, PltEntryAddr, Index, RelOff);
> +    return;
> +  }
> +  write32le(Buf + 0, PltData[0] | ((Offset >> 20) & 0xff));
> +  write32le(Buf + 4, PltData[1] | ((Offset >> 12) & 0xff));
> +  write32le(Buf + 8, PltData[2] | (Offset & 0xfff));
> +  write32le(Buf + 12, TrapInstr); // Pad to 16-byte boundary
> +}
> +
>  void ARM::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const {
>    auto *IS = cast<InputSection>(ISD);
>    addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS);


More information about the llvm-commits mailing list