59 changes: 59 additions & 0 deletions lld/test/ELF/arm-branch.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar
// RUN: echo "SECTIONS { \
// RUN: .callee1 : { *(.callee_low) } \
// RUN: .caller : { *(.text) } \
// RUN: .callee2 : { *(.callee_high) } } " > %t.script
// RUN: ld.lld --script %t.script %t %tfar -o %t2 2>&1
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
// REQUIRES: arm
.syntax unified
.section .callee_low, "ax",%progbits
.align 2
.type callee_low,%function
callee_low:
bx lr

.section .text, "ax",%progbits
.globl _start
.balign 0x10000
.type _start,%function
_start:
bl callee_low
b callee_low
beq callee_low
bl callee_high
b callee_high
bne callee_high
bl far
b far
bgt far
bx lr

.section .callee_high, "ax",%progbits
.align 2
.type callee_high,%function
callee_high:
bx lr

// CHECK: Disassembly of section .caller:
// CHECK-NEXT: _start:
// S(callee_low) = 0xb4 P = 0x10000 A = -8 = -0xff54 = -65364
// CHECK-NEXT: 10000: 2b c0 ff eb bl #-65364 <callee_low>
// S(callee_low) = 0xb4 P = 0x10004 A = -8 = -0xff58 = -65368
// CHECK-NEXT: 10004: 2a c0 ff ea b #-65368 <callee_low>
// S(callee_low) = 0xb4 P = 0x10008 A = -8 = -0xff5c -65372
// CHECK-NEXT: 10008: 29 c0 ff 0a beq #-65372 <callee_low>
// S(callee_high) = 0x10028 P = 0x1000c A = -8 = 0x14 = 20
// CHECK-NEXT: 1000c: 05 00 00 eb bl #20 <callee_high>
// S(callee_high) = 0x10028 P = 0x10010 A = -8 = 0x10 = 16
// CHECK-NEXT: 10010: 04 00 00 ea b #16 <callee_high>
// S(callee_high) = 0x10028 P = 0x10014 A = -8 = 0x0c =12
// CHECK-NEXT: 10014: 03 00 00 1a bne #12 <callee_high>
// S(far) = 0x201001c P = 0x10018 A = -8 = 0x1fffffc = 33554428
// CHECK-NEXT: 10018: ff ff 7f eb bl #33554428
// S(far) = 0x201001c P = 0x1001c A = -8 = 0x1fffff8 = 33554424
// CHECK-NEXT: 1001c: fe ff 7f ea b #33554424
// S(far) = 0x201001c P = 0x10020 A = -8 = 0x1fffff4 = 33554420
// CHECK-NEXT: 10020: fd ff 7f ca bgt #33554420
// CHECK-NEXT: 10024: 1e ff 2f e1 bx lr
81 changes: 81 additions & 0 deletions lld/test/ELF/arm-copy.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// REQUIRES: arm
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/relocation-copy-arm.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so -o %t3
// RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CODE %s
// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s

// Copy relocations R_ARM_COPY are required for y and z
.syntax unified
.text
.globl _start
_start:
movw r2,:lower16: y
movt r2,:upper16: y
ldr r3,[pc,#4]
ldr r3,[r3,#0]
.rodata
.word z

// CHECK: Name: .bss
// CHECK-NEXT: Type: SHT_NOBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x13000
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 8
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment: 16

// CHECK: Relocations [
// CHECK-NEXT: Section (5) .rel.dyn {
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x13000
// CHECK-NEXT: Type: R_ARM_COPY
// CHECK-NEXT: Symbol: y
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset: 0x13004
// CHECK-NEXT: Type: R_ARM_COPY
// CHECK-NEXT: Symbol: z
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: }

// CHECK: Symbols [
// CHECK: Name: y
// CHECK-NEXT: Value: 0x13000
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other:
// CHECK-NEXT: Section: .bss
// CHECK: Name: z
// CHECK-NEXT: Value: 0x13004
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .bss

// CODE: Disassembly of section .text:
// CODE-NEXT: _start:
// S(y) = 0x13000, A = 0
// (S + A) & 0x0000ffff = 0x3000 = #12288
// CODE-NEXT: 11000: 00 20 03 e3 movw r2, #12288
// S(y) = 0x13000, A = 0
// ((S + A) & 0xffff0000) >> 16 = 0x1
// CODE-NEXT: 11004: 01 20 40 e3 movt r2, #1
// CODE-NEXT: 11008: 04 30 9f e5 ldr r3, [pc, #4]
// CODE-NEXT: 1100c: 00 30 93 e5 ldr r3, [r3]


// RODATA: Contents of section .rodata:
// S(z) = 0x13004
// RODATA-NEXT: 10114 04300100
63 changes: 63 additions & 0 deletions lld/test/ELF/arm-data-prel.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o
// RUN: echo "SECTIONS { \
// RUN: .text : { *(.text) } \
// RUN: .ARM.exidx : { *(.ARM.exidx) } \
// RUN: .ARM.exidx.TEST1 : { *(.ARM.exidx.TEST1) } \
// RUN: .TEST1 : { *(.TEST1) } } " > %t.script
// RUN: ld.lld --script %t.script %t.o -o %t
// RUN: llvm-readobj -s -sd %t | FileCheck --check-prefix=CHECK %s
// REQUIRES: arm

// The R_ARM_PREL31 relocation is used in by the .ARM.exidx exception tables
// bit31 of the place denotes whether the field is an inline table entry
// (bit31=1) or relocation (bit31=0)
// The linker must preserve the value of bit31

// This test case is adapted from llvm/test/MC/ARM/eh-compact-pr0.s
// We use a linker script to place the .ARM.exidx sections in between
// the code sections so that we can test positive and negative offsets
.syntax unified

.section .TEST1, "ax",%progbits
.globl _start
.align 2
.type _start,%function
_start:
.fnstart
.save {r11, lr}
push {r11, lr}
.setfp r11, sp
mov r11, sp
pop {r11, lr}
mov pc, lr
.fnend

.section .text, "ax",%progbits
// The generated .ARM.exidx section will refer to the personality
// routine __aeabi_unwind_cpp_pr0. Provide a dummy implementation
// to stop an undefined symbol error
.globl __aeabi_unwind_cpp_pr0
.align 2
.type __aeabi_unwind_cpp_pr0,%function
__aeabi_unwind_cpp_pr0:
.fnstart
bx lr
.fnend

// The expected value of the exception table is
// Word0 0 in bit 31, -4 encoded in 31-bit signed offset
// Word1 Inline table entry EHT Inline Personality Routine #0
// CHECK: Name: .ARM.exidx
// CHECK: SectionData (
// CHECK: 0000: FCFFFF7F B0B0B080
// CHECK: )

// The expected value of the exception table is
// Word0 0 in bit 31, +8 encoded in 31-bit signed offset
// Word1 Inline table entry EHT Inline Personality Routine #0
// set vsp = r11
// pop r11, r14
// CHECK: Name: .ARM.exidx.TEST1
// CHECK: SectionData (
// CHECK: 0000: 08000000 80849B80
// CHECK: )
20 changes: 20 additions & 0 deletions lld/test/ELF/arm-data-relocs.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/abs256.s -o %t256.o
// RUN: ld.lld %t %t256.o -o %t2
// RUN: llvm-objdump -d %t2 | FileCheck %s
// REQUIRES: arm
.syntax unified
.globl _start
_start:
.section .R_ARM_ABS32POS, "ax",%progbits
.word foo + 0x24

// S = 0x100, A = 0x24
// S + A = 0x124
// CHECK: Disassembly of section .R_ARM_ABS32POS:
// CHECK: 11000: 24 01 00 00
.section .R_ARM_ABS32NEG, "ax",%progbits
.word foo - 0x24
// S = 0x100, A = -0x24
// CHECK: Disassembly of section .R_ARM_ABS32NEG:
// CHECK: 11004: dc 00 00 00
63 changes: 63 additions & 0 deletions lld/test/ELF/arm-fpic-got.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// REQUIRES: arm
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
// RUN: ld.lld %t.o -o %t
// RUN: llvm-readobj -s %t | FileCheck %s
// RUN: llvm-readobj -s -symbols %t | FileCheck -check-prefix=SYMBOLS %s
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s

// Test the R_ARM_GOT_PREL relocation
.syntax unified
.text
.globl _start
.align 2
_start:
ldr r0, .LCPI0_0
.LPC0_0:
ldr r0, [pc, r0]
ldr r0, [r0]
bx lr
.LCPI0_0:
.Ltmp0:
// Generate R_ARM_GOT_PREL
.long val(GOT_PREL)-((.LPC0_0+8)-.Ltmp0)

.data
.type val,%object
.globl val
.align 2
val:
.long 10
.size val, 4

// CHECK: Section {
// CHECK: Name: .got
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x12000
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment: 4
// CHECK-NEXT: EntrySize:

// SYMBOLS: Name: val
// SYMBOLS-NEXT: Value: 0x13000
// SYMBOLS-NEXT: Size: 4
// SYMBOLS-NEXT: Binding: Global
// SYMBOLS-NEXT: Type: Object
// SYMBOLS-NEXT: Other:
// SYMBOLS-NEXT: Section: .data

// CODE: Disassembly of section .text:
// CODE-NEXT: _start:
// CODE-NEXT: 11000: 08 00 9f e5 ldr r0, [pc, #8]
// CODE-NEXT: 11004: 00 00 9f e7 ldr r0, [pc, r0]
// CODE-NEXT: 11008: 00 00 90 e5 ldr r0, [r0]
// CODE-NEXT: 1100c: 1e ff 2f e1 bx lr
// CODE: $d.1:
// 0x11004 + 0x0ff4 + 8 = 0x12000 = .got
// CODE-NEXT: 11010: f4 0f 00 00
27 changes: 27 additions & 0 deletions lld/test/ELF/arm-gnu-ifunc-nosym.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
// RUN: ld.lld -static %t.o -o %tout
// RUN: llvm-readobj -symbols %tout | FileCheck %s
// REQUIRES: arm

// Check that no __rel_iplt_end/__rel_iplt_start
// appear in symtab if there are no references to them.
// CHECK: Symbols [
// CHECK-NOT: __rel_iplt_end
// CHECK-NOT: __rel_iplt_start
// CHECK: ]
.syntax unified
.text
.type foo STT_GNU_IFUNC
.globl foo
foo:
bx lr

.type bar STT_GNU_IFUNC
.globl bar
bar:
bx lr

.globl _start
_start:
bl foo
bl bar
131 changes: 131 additions & 0 deletions lld/test/ELF/arm-gnu-ifunc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
// RUN: ld.lld -static %t.o -o %tout
// RUN: llvm-objdump -triple armv7a-none-linux-gnueabi -d %tout | FileCheck %s --check-prefix=DISASM
// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s
// REQUIRES: arm
.syntax unified
.text
.type foo STT_GNU_IFUNC
.globl foo
foo:
bx lr

.type bar STT_GNU_IFUNC
.globl bar
bar:
bx lr

.globl _start
_start:
bl foo
bl bar
movw r0,:lower16:__rel_iplt_start
movt r0,:upper16:__rel_iplt_start
movw r0,:lower16:__rel_iplt_end
movt r0,:upper16:__rel_iplt_end

// CHECK: Sections [
// CHECK: Section {
// CHECK: Index: 1
// CHECK-NEXT: Name: .rel.plt
// CHECK-NEXT: Type: SHT_REL
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: ]
// CHECK-NEXT: Address: [[REL:.*]]
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 16
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment: 4
// CHECK-NEXT: EntrySize: 8
// CHECK-NEXT: }
// CHECK: Relocations [
// CHECK-NEXT: Section (1) .rel.plt {
// CHECK-NEXT: 0x1200C R_ARM_IRELATIVE
// CHECK-NEXT: 0x12010 R_ARM_IRELATIVE
// CHECK-NEXT: }
// CHECK-NEXT:]
// CHECK: Symbols [
// CHECK: Symbol {
// CHECK: Name: __rel_iplt_end
// CHECK-NEXT: Value: 0x100E4
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other [
// CHECK-NEXT: STV_HIDDEN
// CHECK-NEXT: ]
// CHECK-NEXT: Section: .rel.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: __rel_iplt_start
// CHECK-NEXT: Value: 0x100D4
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other [
// CHECK-NEXT: STV_HIDDEN
// CHECK-NEXT: ]
// CHECK-NEXT: Section: .rel.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: _start (6)
// CHECK-NEXT: Value: 0x11008
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other:
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar
// CHECK-NEXT: Value: 0x11004
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: GNU_IFunc
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo
// CHECK-NEXT: Value: 0x11000
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: GNU_IFunc
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }

// 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: 09 00 00 eb bl #36
// DISASM-NEXT: 1100c: 0c 00 00 eb bl #48
// DISASM-NEXT: 11010: d4 00 00 e3 movw r0, #212
// DISASM-NEXT: 11014: 01 00 40 e3 movt r0, #1
// r0 = 212 + 1 * 65536 = 100D4 = __rel_iplt_start
// DISASM-NEXT: 11018: e4 00 00 e3 movw r0, #228
// DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1
// r1 = 228 + 1 * 65536 = 100E4 = __rel_iplt_end
// DISASM-NEXT: Disassembly of section .plt:
// DISASM-NEXT: .plt:
// 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]!
// 0x0fd0 + 0x11028 + 0x8 = 0x12000
// DISASM-NEXT: 11030: d0 0f 00 00
// 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]
// 0x0fcc + 0x11038 + 0x8 = 0x1200C
// DISASM-NEXT: 11040: cc 0f 00 00
// 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]
// 0x0fc0 + 0x11048 + 0x8 = 0x12010
// DISASM-NEXT: 11050: c0 0f 00 00
53 changes: 53 additions & 0 deletions lld/test/ELF/arm-got-relative.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// REQUIRES: arm
// RUN: llvm-mc -position-independent -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
// RUN: ld.lld %t.o -shared -o %t
// RUN: llvm-readobj -s -symbols -dyn-relocations %t | FileCheck %s
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s
.syntax unified
.text
.globl _start
.align 2
_start:
.type _start, %function
ldr r3, .LGOT
ldr r2, .LGOT+4
.LPIC:
add r0, pc, r3
bx lr
.align 2
.LGOT:
// gas implicitly uses (GOT_PREL) for _GLOBAL_OFFSET_TABLE_ in PIC
// llvm-mc needs the (GOT_PREL) suffix or it generates R_ARM_REL32
.word _GLOBAL_OFFSET_TABLE_(GOT_PREL) - (.LPIC+8)
.word function(GOT)

.globl function
.align 2
function:
.type function, %function
bx lr

// CHECK: Dynamic Relocations {
// CHECK-NEXT: 0x204C R_ARM_GLOB_DAT function 0x0

// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (16)
// CHECK-NEXT: Value: 0x0
// CHECK-NEXT: Size:
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other [
// CHECK-NEXT: STV_HIDDEN
// CHECK-NEXT: ]
// CHECK-NEXT: Section: Absolute

// CODE: Disassembly of section .text:
// CODE-NEXT: _start:
// CODE-NEXT: 1000: 08 30 9f e5 ldr r3, [pc, #8]
// CODE-NEXT: 1004: 08 20 9f e5 ldr r2, [pc, #8]
// CODE-NEXT: 1008: 03 00 8f e0 add r0, pc, r3
// CODE-NEXT: 100c: 1e ff 2f e1 bx lr
// CODE:$d.1:
// (_GLOBAL_OFFSET_TABLE_ = 0x2048) - (0x1008 + 8) 0x1038
// CODE-NEXT: 1010: 38 10 00 00
// (Got(function) - GotBase = 0x4
// CODE-NEXT: 1014: 04 00 00 00
74 changes: 74 additions & 0 deletions lld/test/ELF/arm-gotoff.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabi %s -o %t.o
// RUN: ld.lld %t.o -o %t
// RUN: llvm-readobj -s -r -t %t | FileCheck %s
// RUN: llvm-objdump -triple=armv7a-linux-gnueabi -d %t | FileCheck --check-prefix=DISASM %s
// REQUIRES: arm

// Test the R_ARM_GOTOFF32 relocation

// CHECK: Name: .got
// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x12000
// CHECK-NEXT: Offset: 0x2000
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment:

// CHECK: Name: .bss
// CHECK-NEXT: Type: SHT_NOBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x12000
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 20
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment: 1

// CHECK-NEXT: EntrySize: 0

// CHECK: Symbol {
// CHECK: Name: bar
// CHECK-NEXT: Value: 0x12000
// CHECK-NEXT: Size: 10
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .bss
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: obj
// CHECK-NEXT: Value: 0x1200A
// CHECK-NEXT: Size: 10
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .bss

// DISASM: Disassembly of section .text:
// DISASM-NEXT :_start:
// DISASM-NEXT 11000: 1e ff 2f e1 bx lr
// Offset 0 from .got = bar
// DISASM 11004: 00 00 00 00
// Offset 10 from .got = obj
// DISASM-NEXT 11008: 0a 00 00 00
// Offset 15 from .got = obj +5
// DISASM-NEXT 1100c: 0f 00 00 00
.syntax unified
.globl _start
_start:
bx lr
.word bar(GOTOFF)
.word obj(GOTOFF)
.word obj(GOTOFF)+5
.type bar, %object
.comm bar, 10
.type obj, %object
.comm obj, 10
53 changes: 53 additions & 0 deletions lld/test/ELF/arm-mov-relocs.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-unknown-linux-gnueabi %s -o %t
// RUN: ld.lld %t -o %t2
// RUN: llvm-objdump -d %t2 -triple=armv7a-unknown-linux-gnueabi | FileCheck %s
// REQUIRES: arm

// Test the R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS relocations
.syntax unified
.globl _start
_start:
.section .R_ARM_MOVW_ABS_NC, "ax",%progbits
movw r0, :lower16:label
movw r1, :lower16:label1
movw r2, :lower16:label2 + 4
movw r3, :lower16:label3
movw r4, :lower16:label3 + 4
// CHECK: Disassembly of section .R_ARM_MOVW_ABS_NC
// CHECK: movw r0, #0
// CHECK: movw r1, #4
// CHECK: movw r2, #12
// CHECK: movw r3, #65532
// CHECK: movw r4, #0
.section .R_ARM_MOVT_ABS, "ax",%progbits
movt r0, :upper16:label
movt r1, :upper16:label1
// FIXME: We shouldn't need to multiply by 65536.
// arguably llvm-mc incorrectly assembles addends for
// SHT_REL relocated movt instructions. When there is a relocation
// the interpretation of the addend for SHT_REL is not shifted
movt r2, :upper16:label2 + (4 * 65536)
movt r3, :upper16:label3
// FIXME: We shouldn't need to multiply by 65536 see comment above.
movt r4, :upper16:label3 + (4 * 65536)
// CHECK: Disassembly of section .R_ARM_MOVT_ABS
// CHECK: movt r0, #2
// CHECK: movt r1, #2
// CHECK: movt r2, #2
// CHECK: movt r3, #2
// CHECK: movt r4, #3

.section .destination, "aw",%progbits
.balign 65536
label:
.word 0
label1:
.word 1
label2:
.word 2
// Test label3 is immediately below 2^16 alignment boundary
.space 65536 - 16
label3:
.word 3
// label3 + 4 is on a 2^16 alignment boundary
.word 4
90 changes: 90 additions & 0 deletions lld/test/ELF/arm-plt-reloc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-plt-reloc.s -o %t1
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2
// RUN: ld.lld %t1 %t2 -o %t
// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t | FileCheck %s
// RUN: ld.lld -shared %t1 %t2 -o %t3
// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSO %s
// RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s
// REQUIRES: arm
//
// Test PLT entry generation
.syntax unified
.text
.align 2
.globl _start
.type _start,%function
_start:
b func1
bl func2
beq func3

// Executable, expect no PLT
// CHECK: Disassembly of section .text:
// CHECK-NEXT: func1:
// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr
// CHECK: func2:
// CHECK-NEXT: 11004: 1e ff 2f e1 bx lr
// CHECK: func3:
// CHECK-NEXT: 11008: 1e ff 2f e1 bx lr
// CHECK: _start:
// CHECK-NEXT: 1100c: fb ff ff ea b #-20 <func1>
// CHECK-NEXT: 11010: fb ff ff eb bl #-20 <func2>
// CHECK-NEXT: 11014: fb ff ff 0a beq #-20 <func3>

// Expect PLT entries as symbols can be preempted
// DSO: Disassembly of section .text:
// DSO-NEXT: func1:
// DSO-NEXT: 1000: 1e ff 2f e1 bx lr
// DSO: func2:
// DSO-NEXT: 1004: 1e ff 2f e1 bx lr
// DSO: func3:
// 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:
// DSO-NEXT:.plt:
// 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 + 1fd0 = 0x3000
// DSO-NEXT: 1030: d0 1f 00 00
// 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 + 1fcc = 0x300c
// DSO-NEXT: 1040: cc 1f 00 00
// 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 + 1fc0 = 0x3010
// DSO-NEXT: 1050: c0 1f 00 00
// 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 + 1fb4 = 0x3014
// DSO-NEXT: 1060: b4 1f 00 00

// DSOREL: Name: .got.plt
// DSOREL-NEXT: Type: SHT_PROGBITS
// DSOREL-NEXT: Flags [
// DSOREL-NEXT: SHF_ALLOC
// DSOREL-NEXT: SHF_WRITE
// DSOREL-NEXT: ]
// DSOREL-NEXT: Address: 0x3000
// DSOREL-NEXT: Offset:
// DSOREL-NEXT: Size: 24
// DSOREL-NEXT: Link:
// DSOREL-NEXT: Info:
// DSOREL-NEXT: AddressAlignment: 4
// DSOREL-NEXT: EntrySize:
// DSOREL: Relocations [
// DSOREL-NEXT: Section (4) .rel.plt {
// DSOREL-NEXT: 0x300C R_ARM_JUMP_SLOT func1 0x0
// DSOREL-NEXT: 0x3010 R_ARM_JUMP_SLOT func2 0x0
// DSOREL-NEXT: 0x3014 R_ARM_JUMP_SLOT func3 0x0