REQUIRES: aarch64
## Test handling of addends taken from the relocated word or instruction
## in AArch64 relocation sections of type SHT_REL. These can be generated
## by assemblers other than LLVM, in particular the legacy 'armasm'.
##
## llvm-mc will only generate SHT_RELA when targeting AArch64. So to make
## an input file with SHT_REL, we assemble our test source file, then
## round-trip via YAML and do some seddery to change the type of the
## relocation section. Since all the relocations were made manually with
## .reloc directives containing no addend, this succeeds.
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=aarch64 relocs.s -o rela.o
# RUN: obj2yaml rela.o -o rela.yaml
# RUN: sed "s/\.rela/\.rel/;s/SHT_RELA/SHT_REL/" rela.yaml > rel.yaml
# RUN: yaml2obj rel.yaml -o rel.o
# RUN: llvm-mc -filetype=obj -triple=aarch64 symbols.s -o symbols.o
# RUN: ld.lld rel.o symbols.o -o a.out --section-start=.data=0x100000 --section-start=.text=0x200000
# RUN: llvm-objdump -s a.out | FileCheck %s --check-prefix=DATA
# RUN: llvm-objdump -d a.out | FileCheck %s --check-prefix=CODE
#--- symbols.s
// Source file containing the values of target symbols for the relocations. If
// we don't keep these in their own file, then llvm-mc is clever enough to
// resolve some of the relocations during assembly, even though they're written
// as explicit .reloc directives. But we want the relocations to be present in
// the object file, so that yaml2obj can change their type and we can test
// lld's handling of the result. So we ensure that llvm-mc can't see both the
// .reloc and the target symbol value at the same time.
.globl abs16
.globl abs32
.globl abs64
.globl big64
.globl pcrel
.globl data
.globl branchtarget
.globl calltarget
.equ abs16, 0x9999
.equ data, 0x100000
.equ branchtarget, 0x200100
.equ calltarget, 0x02000100
.equ pcrel, 0x245678
.equ abs32, 0x88888888
.equ abs64, 0x7777777777777777
.equ big64, 0x77ffffffffffff77
#--- relocs.s
// Source file containing the test instructions and their relocations, with the
// FileCheck comments interleaved.
// DATA: Contents of section .data:
.data
// First test absolute data relocations. For each one I show the expected
// value in a comment, and then expect a line in llvm-objdump -s containing
// all the values together.
// 0x7777777777777777 + 0x1234567887654321 = 0x89abcdeffedcba98
.reloc ., R_AARCH64_ABS64, abs64
.xword 0x1234567887654321
// 0x88888888 + 0x12344321 = 0x9abccba9
.reloc ., R_AARCH64_ABS32, abs32
.word 0x12344321
// 0x9999 + 0x1234 = 0xabcd
.reloc ., R_AARCH64_ABS16, abs16
.hword 0x1234
// DATA-NEXT: 100000 98badcfe efcdab89 a9cbbc9a cdab
.balign 16
// Test relative data relocs, each subtracting the address of the relocated
// word.
// 0x100000 + 0x1234567887654321 - 0x100010 = 0x1234567887654311
.reloc ., R_AARCH64_PREL64, data
.xword 0x1234567887654321
// 0x100000 + 0x12344321 - 0x100018 = 0x12344309
.reloc ., R_AARCH64_PREL32, data
.word 0x12344321
// 0x100000 + 0x1234 - 0x10001c = 0x1218
.reloc ., R_AARCH64_PREL16, data
.hword 0x1234
// DATA-NEXT: 100010 11436587 78563412 09433412 1812
// CODE: 0000000000200000 <_start>:
.text
.globl _start
_start:
// Full set of 4 instructions loading the constant 'abs64' and adding 0x1234 to
// it.
// Expected constant is 0x7777777777777777 + 0x1234 = 0x77777777777789ab
.reloc ., R_AARCH64_MOVW_UABS_G0_NC, abs64
movz x0, #0x1234
// CODE-NEXT: 200000: d2913560 mov x0, #0x89ab
.reloc ., R_AARCH64_MOVW_UABS_G1_NC, abs64
movk x0, #0x1234, lsl #16
// CODE-NEXT: 200004: f2aeeee0 movk x0, #0x7777, lsl #16
.reloc ., R_AARCH64_MOVW_UABS_G2_NC, abs64
movk x0, #0x1234, lsl #32
// CODE-NEXT: 200008: f2ceeee0 movk x0, #0x7777, lsl #32
.reloc ., R_AARCH64_MOVW_UABS_G3, abs64
movk x0, #0x1234, lsl #48
// CODE-NEXT: 20000c: f2eeeee0 movk x0, #0x7777, lsl #48
// The same, but this constant has ffff in the middle 32 bits, forcing carries
// to be propagated.
// Expected constant: 0x77ffffffffffff77 + 0x1234 = 0x78000000000011ab
.reloc ., R_AARCH64_MOVW_UABS_G0_NC, big64
movz x0, #0x1234
// CODE-NEXT: 200010: d2823560 mov x0, #0x11ab
.reloc ., R_AARCH64_MOVW_UABS_G1_NC, big64
movk x0, #0x1234, lsl #16
// CODE-NEXT: 200014: f2a00000 movk x0, #0x0, lsl #16
.reloc ., R_AARCH64_MOVW_UABS_G2_NC, big64
movk x0, #0x1234, lsl #32
// CODE-NEXT: 200018: f2c00000 movk x0, #0x0, lsl #32
.reloc ., R_AARCH64_MOVW_UABS_G3, big64
movk x0, #0x1234, lsl #48
// CODE-NEXT: 20001c: f2ef0000 movk x0, #0x7800, lsl #48
// Demonstrate that offsets are treated as signed: this one is taken to be
// -0x1234. (If it were +0xedcc then you'd be able to tell the difference by
// the carry into the second halfword.)
// Expected value: 0x7777777777777777 - 0x1234 = 0x7777777777776543
.reloc ., R_AARCH64_MOVW_UABS_G0_NC, abs64
movz x0, #0xedcc
// CODE-NEXT: 200020: d28ca860 mov x0, #0x6543
.reloc ., R_AARCH64_MOVW_UABS_G1_NC, abs64
movk x0, #0xedcc, lsl #16
// CODE-NEXT: 200024: f2aeeee0 movk x0, #0x7777, lsl #16
.reloc ., R_AARCH64_MOVW_UABS_G2_NC, abs64
movk x0, #0xedcc, lsl #32
// CODE-NEXT: 200028: f2ceeee0 movk x0, #0x7777, lsl #32
.reloc ., R_AARCH64_MOVW_UABS_G3, abs64
movk x0, #0xedcc, lsl #48
// CODE-NEXT: 20002c: f2eeeee0 movk x0, #0x7777, lsl #48
// Check various bits of the ADR immediate, including in particular the low 2
// bits, which are not contiguous with the rest in the encoding.
//
// These values are all 0x245678 + 2^n, except the last one, where the set bit
// of the addend is the top bit, counting as negative, i.e. we expect the value
// 0x254678 - 0x100000 = 0x145678.
.reloc ., R_AARCH64_ADR_PREL_LO21, pcrel
adr x0, .+1
// CODE-NEXT: 200030: 3022b240 adr x0, 0x245679
.reloc ., R_AARCH64_ADR_PREL_LO21, pcrel
adr x0, .+2
// CODE-NEXT: 200034: 5022b220 adr x0, 0x24567a
.reloc ., R_AARCH64_ADR_PREL_LO21, pcrel
adr x0, .+4
// CODE-NEXT: 200038: 1022b220 adr x0, 0x24567c
.reloc ., R_AARCH64_ADR_PREL_LO21, pcrel
adr x0, .+8
// CODE-NEXT: 20003c: 1022b220 adr x0, 0x245680
.reloc ., R_AARCH64_ADR_PREL_LO21, pcrel
adr x0, .+1<<19
// CODE-NEXT: 200040: 1062b1c0 adr x0, 0x2c5678
.reloc ., R_AARCH64_ADR_PREL_LO21, pcrel
adr x0, .-1<<20
// CODE-NEXT: 200044: 10a2b1a0 adr x0, 0x145678
// Now load the same set of values with ADRP+ADD. But because the real ADRP
// instruction shifts its immediate, we must account for that.
.reloc ., R_AARCH64_ADR_PREL_PG_HI21, pcrel
adrp x0, 1<<12
// CODE-NEXT: 200048: b0000220 adrp x0, 0x245000
.reloc ., R_AARCH64_ADD_ABS_LO12_NC, pcrel
add x0, x0, #1
// CODE-NEXT: 20004c: 9119e400 add x0, x0, #0x679
.reloc ., R_AARCH64_ADR_PREL_PG_HI21, pcrel
adrp x0, 2<<12
// CODE-NEXT: 200050: b0000220 adrp x0, 0x245000
.reloc ., R_AARCH64_ADD_ABS_LO12_NC, pcrel
add x0, x0, #2
// CODE-NEXT: 200054: 9119e800 add x0, x0, #0x67a
.reloc ., R_AARCH64_ADR_PREL_PG_HI21, pcrel
adrp x0, 4<<12
// CODE-NEXT: 200058: b0000220 adrp x0, 0x245000
.reloc ., R_AARCH64_ADD_ABS_LO12_NC, pcrel
add x0, x0, #4
// CODE-NEXT: 20005c: 9119f000 add x0, x0, #0x67c
.reloc ., R_AARCH64_ADR_PREL_PG_HI21, pcrel
adrp x0, 8<<12
// CODE-NEXT: 200060: b0000220 adrp x0, 0x245000
.reloc ., R_AARCH64_ADD_ABS_LO12_NC, pcrel
add x0, x0, #8
// CODE-NEXT: 200064: 911a0000 add x0, x0, #0x680
// Starting here, the high bits won't fit in the ADD immediate, so that
// becomes 0, and only the ADRP immediate shows evidence of the addend.
.reloc ., R_AARCH64_ADR_PREL_PG_HI21, pcrel
adrp x0, 1<<(19+12)
// CODE-NEXT: 200068: b0000620 adrp x0, 0x2c5000
.reloc ., R_AARCH64_ADD_ABS_LO12_NC, pcrel
add x0, x0, #0
// CODE-NEXT: 20006c: 9119e000 add x0, x0, #0x678
.reloc ., R_AARCH64_ADR_PREL_PG_HI21, pcrel
adrp x0, -1<<(20+12)
// CODE-NEXT: 200070: b0fffa20 adrp x0, 0x145000
.reloc ., R_AARCH64_ADD_ABS_LO12_NC, pcrel
add x0, x0, #0
// CODE-NEXT: 200074: 9119e000 add x0, x0, #0x678
// Finally, an example with a full 21-bit addend.
// Expected value = 0x245678 + 0xfedcb - 0x100000 = 0x244443
.reloc ., R_AARCH64_ADR_PREL_PG_HI21, pcrel
adrp x0, (0xfedcb-0x100000)<<12
// CODE-NEXT: 200078: 90000220 adrp x0, 0x244000
.reloc ., R_AARCH64_ADD_ABS_LO12_NC, pcrel
add x0, x0, #0xdcb
// CODE-NEXT: 20007c: 91110c00 add x0, x0, #0x443
// PC-relative loads, in which the 19-bit offset is shifted. The offsets are
// the same as the ADRs above, except for the first two, which can't be
// expressed by pc-relative LDR with an offset shifted left 2.
//
// (The input syntax is confusing here. I'd normally expect to write this as
// `ldr x0, [pc, #offset]`, but LLVM writes just `#offset`.)
.reloc ., R_AARCH64_LD_PREL_LO19, pcrel
ldr w0, #4
// CODE-NEXT: 200080: 1822afe0 ldr w0, 0x24567c
.reloc ., R_AARCH64_LD_PREL_LO19, pcrel
ldr w0, #8
// CODE-NEXT: 200084: 1822afe0 ldr w0, 0x245680
.reloc ., R_AARCH64_LD_PREL_LO19, pcrel
ldr w0, #1<<19
// CODE-NEXT: 200088: 1862af80 ldr w0, 0x2c5678
.reloc ., R_AARCH64_LD_PREL_LO19, pcrel
ldr w0, #-1<<20
// CODE-NEXT: 20008c: 18a2af60 ldr w0, 0x145678
// For these, the branch target is 0x200100 plus powers of 2, except the offset
// 2^15, which is negative, because the addend is treated as signed.
.reloc ., R_AARCH64_TSTBR14, branchtarget
tbnz x1, #63, #4
// CODE-NEXT: 200090: b7f803a1 tbnz x1, #0x3f, 0x200104
.reloc ., R_AARCH64_TSTBR14, branchtarget
tbnz x1, #62, #8
// CODE-NEXT: 200094: b7f003a1 tbnz x1, #0x3e, 0x200108
.reloc ., R_AARCH64_TSTBR14, branchtarget
tbnz x1, #61, #1<<14
// CODE-NEXT: 200098: b7ea0341 tbnz x1, #0x3d, 0x204100
.reloc ., R_AARCH64_TSTBR14, branchtarget
tbnz x1, #60, #-1<<15
// CODE-NEXT: 20009c: b7e40321 tbnz x1, #0x3c, 0x1f8100
// CONDBR19 is used for both cbz/cbnz and B.cond, so test both at once. Base
// offset is the same again (from 0x200100), but this time, offsets can go up
// to 2^20.
.reloc ., R_AARCH64_CONDBR19, branchtarget
cbnz x2, #4
// CODE-NEXT: 2000a0: b5000322 cbnz x2, 0x200104
.reloc ., R_AARCH64_CONDBR19, branchtarget
b.eq #8
// CODE-NEXT: 2000a4: 54000320 b.eq 0x200108
.reloc ., R_AARCH64_CONDBR19, branchtarget
cbz x2, #1<<19
// CODE-NEXT: 2000a8: b44002c2 cbz x2, 0x280100
.reloc ., R_AARCH64_CONDBR19, branchtarget
b.vs #-1<<20
// CODE-NEXT: 2000ac: 548002a6 b.vs 0x100100
// And for BL and B, the offsets go up to 2^25.
.reloc ., R_AARCH64_CALL26, calltarget
bl #4
// CODE-NEXT: 2000b0: 94780015 bl 0x2000104
.reloc ., R_AARCH64_CALL26, calltarget
bl #8
// CODE-NEXT: 2000b4: 94780015 bl 0x2000108
.reloc ., R_AARCH64_CALL26, calltarget
bl #1<<24
// CODE-NEXT: 2000b8: 94b80012 bl 0x3000100
.reloc ., R_AARCH64_CALL26, calltarget
bl #-1<<25
// CODE-NEXT: 2000bc: 97f80011 bl 0x100
.reloc ., R_AARCH64_JUMP26, calltarget
b #4
// CODE-NEXT: 2000c0: 14780011 b 0x2000104
.reloc ., R_AARCH64_JUMP26, calltarget
b #8
// CODE-NEXT: 2000c4: 14780011 b 0x2000108
.reloc ., R_AARCH64_JUMP26, calltarget
b #1<<24
// CODE-NEXT: 2000c8: 14b8000e b 0x3000100
.reloc ., R_AARCH64_JUMP26, calltarget
b #-1<<25
// CODE-NEXT: 2000cc: 17f8000d b 0x100