diff --git a/docs/DeveloperDocs/ARM-Relocations.md b/docs/DeveloperDocs/ARM-Relocations.md index 6f8af0c62c..7ba302cd47 100644 --- a/docs/DeveloperDocs/ARM-Relocations.md +++ b/docs/DeveloperDocs/ARM-Relocations.md @@ -69,7 +69,11 @@ movt r0, #:upper16:symbol @ R_ARM_THM_MOVT_ABS | `R_ARM_THM_MOVT_BREL` | `S + A - P` | `[31:16]` | none | | `R_ARM_THM_MOVW_BREL_NC` | `((S + A) \| T) - B(S)` | `[15:0]` | none | | `R_ARM_THM_MOVW_BREL` | `((S + A) \| T) - B(S)` | `[15:0]` | none | -| `R_ARM_ALU_PC_G0` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | none | +| `R_ARM_ALU_PC_G0` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | overflow checked | +| `R_ARM_ALU_PC_G0_NC` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | none (truncates) | +| `R_ARM_ALU_PC_G1` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | overflow checked | +| `R_ARM_ALU_PC_G1_NC` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | none (truncates) | +| `R_ARM_ALU_PC_G2` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | overflow checked | | `R_ARM_LDR_PC_G2` | `S + A - P` | imm12 (bits 11:0) | [0, 4095] | | `R_ARM_LDR_PC_G0` | `S + A - P` | imm12 (bits 11:0) | [0, 4095] | @@ -160,10 +164,6 @@ The table below lists every relocation that ELD's ARM backend maps to the `unsup | 54 | `R_ARM_THM_PC12` | Thumb-2 LDR/STR 12-bit PC-relative | | | 55 | `R_ARM_ABS32_NOI` | 32-bit absolute, no interworking bit | | | 56 | `R_ARM_REL32_NOI` | 32-bit PC-relative, no interworking bit | | -| 57 | `R_ARM_ALU_PC_G0_NC` | Group reloc — ALU PC-relative G0, no overflow | Implement ALU_PC_G group | -| 59 | `R_ARM_ALU_PC_G1_NC` | Group reloc — ALU PC-relative G1, no overflow | Implement ALU_PC_G group | -| 60 | `R_ARM_ALU_PC_G1` | Group reloc — ALU PC-relative G1 | Implement ALU_PC_G group | -| 61 | `R_ARM_ALU_PC_G2` | Group reloc — ALU PC-relative G2 | Implement ALU_PC_G group | | 62 | `R_ARM_LDR_PC_G1` | Group reloc — LDR PC-relative G1 | Implement LDR PC-group | | 64 | `R_ARM_LDRS_PC_G0` | Group reloc — LDRD/STRD PC-relative G0 | Implement LDRS PC-group | | 65 | `R_ARM_LDRS_PC_G1` | Group reloc — LDRD/STRD PC-relative G1 | Implement LDRS PC-group | @@ -218,7 +218,6 @@ The following discrepancies or gaps were found when comparing this document agai | `R_ARM_TLS_LE32` expression | Document shows `S + A + 2*WordSize + ...`; ABI defines it as `S + A - tp` (offset from thread pointer) | Fix expression in TLS table to `S + A - tp` | | `R_ARM_GOT_BREL` bits column | Document shows `12`; ABI says the relocation places a 32-bit GOT-relative offset — the `12` refers to LDR's 12-bit immediate encoding, which is an instruction constraint, not the relocation size | Clarify as `32` with a note that the offset must fit in 12 bits | | `R_ARM_SBREL32` | Documented as identical to `R_ARM_REL32`; ABI marks it as using the segment base `B(S)` rather than `P`, so the formula is `((S+A)\|T) - B(S)` not `-P` | Fix expression to `((S + A) \| T) - B(S)` | -| `R_ARM_ALU_PC_G0` (type 58) | Documented in this file and handled by ELD via the `alu_pc` handler; the G1/G2 variants and the `_NC` forms (57, 59-61) are unsupported — not noted in the PC-relative table | Add a note that only G0 is supported | | Thumb branch ranges | `R_ARM_THM_CALL` and `R_ARM_THM_JUMP24` are shown with `±16 MB` range; ABI specifies the range depends on whether J1J2 encoding is available (±4 MB without it) | Add conditional range note matching the Thumb Branch table in the Veneers section | | `R_ARM_TARGET2` | Handled by ELD (as `target2`) but not documented in any section of this file | Add `R_ARM_TARGET2` to the PC-relative or absolute table with a note that its behaviour (ABS32 or GOT-relative) is controlled by a linker option | | Deprecated relocations | `R_ARM_PC24` and `R_ARM_PLT32` are listed in the Branch section without noting they are deprecated in favour of `R_ARM_CALL`/`R_ARM_JUMP24` | Add deprecation note | diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h index 2d94ee0563..81aee53391 100644 --- a/lib/Target/ARM/ARMRelocationFunctions.h +++ b/lib/Target/ARM/ARMRelocationFunctions.h @@ -50,7 +50,11 @@ DECL_ARM_APPLY_RELOC_FUNC(thm_jump8) \ DECL_ARM_APPLY_RELOC_FUNC(thm_jump11) \ DECL_ARM_APPLY_RELOC_FUNC(thm_jump19) \ - DECL_ARM_APPLY_RELOC_FUNC(alu_pc) \ + DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g0) \ + DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g0_nc) \ + DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g1) \ + DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g1_nc) \ + DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g2) \ DECL_ARM_APPLY_RELOC_FUNC(ldr_pc_g2) \ DECL_ARM_APPLY_RELOC_FUNC(ldr_pc_g0) \ DECL_ARM_APPLY_RELOC_FUNC(relocAddPREL1) \ @@ -90,7 +94,11 @@ "R_ARM_THM_MOVW_PREL_NC") \ Func(llvm::ELF::R_ARM_THM_MOVT_PREL, thm_movt_prel, "R_ARM_THM_MOVT_PREL") \ Func(llvm::ELF::R_ARM_THM_JUMP19, thm_jump19, "R_ARM_THM_JUMP19") \ - Func(llvm::ELF::R_ARM_ALU_PC_G0, alu_pc, "R_ARM_ALU_PC_G0") \ + Func(llvm::ELF::R_ARM_ALU_PC_G0, alu_pc_g0, "R_ARM_ALU_PC_G0") \ + Func(llvm::ELF::R_ARM_ALU_PC_G0_NC, alu_pc_g0_nc, "R_ARM_ALU_PC_G0_NC") \ + Func(llvm::ELF::R_ARM_ALU_PC_G1, alu_pc_g1, "R_ARM_ALU_PC_G1") \ + Func(llvm::ELF::R_ARM_ALU_PC_G1_NC, alu_pc_g1_nc, "R_ARM_ALU_PC_G1_NC") \ + Func(llvm::ELF::R_ARM_ALU_PC_G2, alu_pc_g2, "R_ARM_ALU_PC_G2") \ Func(llvm::ELF::R_ARM_LDR_PC_G2, ldr_pc_g2, "R_ARM_LDR_PC_G2") \ Func(llvm::ELF::R_ARM_LDR_PC_G0, ldr_pc_g0, "R_ARM_LDR_PC_G0") \ Func(llvm::ELF::R_ARM_THM_MOVW_BREL_NC, thm_movw_brel, \ diff --git a/lib/Target/ARM/ARMRelocator.cpp b/lib/Target/ARM/ARMRelocator.cpp index 16f13dd997..5611b132e5 100644 --- a/lib/Target/ARM/ARMRelocator.cpp +++ b/lib/Target/ARM/ARMRelocator.cpp @@ -1287,9 +1287,12 @@ Relocator::Result thm_jump19(Relocation &pReloc, ARMRelocator &pParent) { return Relocator::OK; } -// R_ARM_ALU_PC_G0: ((S + A) | T) - P -Relocator::Result alu_pc(Relocation &pReloc, ARMRelocator &pParent) { - // perform static relocation +// R_ARM_ALU_PC_Gn / R_ARM_ALU_PC_Gn_NC: ((S + A) | T) - P +// Shared worker for the whole ALU_PC group family. pGroup selects which +// group's residual to encode and pCheck selects whether encoding failure is +// reported (false for the _NC variants, which silently truncate instead). +static Relocator::Result alu_pc_group(Relocation &pReloc, ARMRelocator &pParent, + unsigned pGroup, bool pCheck) { Relocator::Address S = pParent.getSymValue(&pReloc); Relocator::DWord T = getThumbBit(pParent, pReloc, /*IsJump*/ false); Relocator::Address P = pReloc.place(pParent.module()); @@ -1318,27 +1321,47 @@ Relocator::Result alu_pc(Relocation &pReloc, ARMRelocator &pParent) { Imm = -Imm; } - if (X) { - // Find the current value bit length and the value K_n. - unsigned L = llvm::bit_width(X); - unsigned K = (L < 8 ? 0 : L - 7) >> 1; - // Encode the shifted immediate. - I |= ((X >> (K * 2)) & 0xff) | ((16 - K) & 0xf) << 8; - // Mask off used bits, the residual will be needed for other groups. - X &= llvm::maskTrailingOnes(K * 2); - // For higher groups, the above is repeated. - // If there is still residual, the value cannot be represented. - if (X) { - pReloc.issueUnencodableImmediate(pParent, Imm); - return Relocator::BadImm; - } + // R_ARM_ALU_PC_Gn encodes the group residual as a modified immediate + // (4-bit even rotate + 8-bit constant). + uint32_t Rem = helper_get_rem_for_group(pGroup, X); + unsigned LZ = llvm::countl_zero(Rem) & ~1u; + uint32_t RotImm = Rem; + uint32_t Rot = 0; + if (LZ < 24) { + RotImm = llvm::rotr(Rem, 24 - LZ); + Rot = (LZ + 8) << 7; + } + + if (pCheck && RotImm > 0xff) { + pReloc.issueUnencodableImmediate(pParent, Imm); + return Relocator::BadImm; } - pReloc.target() = I; + pReloc.target() = I | Rot | (RotImm & 0xff); return Relocator::OK; } +Relocator::Result alu_pc_g0(Relocation &pReloc, ARMRelocator &pParent) { + return alu_pc_group(pReloc, pParent, /*pGroup=*/0, /*pCheck=*/true); +} + +Relocator::Result alu_pc_g0_nc(Relocation &pReloc, ARMRelocator &pParent) { + return alu_pc_group(pReloc, pParent, /*pGroup=*/0, /*pCheck=*/false); +} + +Relocator::Result alu_pc_g1(Relocation &pReloc, ARMRelocator &pParent) { + return alu_pc_group(pReloc, pParent, /*pGroup=*/1, /*pCheck=*/true); +} + +Relocator::Result alu_pc_g1_nc(Relocation &pReloc, ARMRelocator &pParent) { + return alu_pc_group(pReloc, pParent, /*pGroup=*/1, /*pCheck=*/false); +} + +Relocator::Result alu_pc_g2(Relocation &pReloc, ARMRelocator &pParent) { + return alu_pc_group(pReloc, pParent, /*pGroup=*/2, /*pCheck=*/true); +} + // R_ARM_PC24: ((S + A) | T) - P // R_ARM_PLT32: ((S + A) | T) - P // R_ARM_JUMP24: ((S + A) | T) - P diff --git a/test/ARM/FromLLD/arm-adr-err-long.s b/test/ARM/FromLLD/arm-adr-err-long.s index bc801e5c2c..38d068a709 100644 --- a/test/ARM/FromLLD/arm-adr-err-long.s +++ b/test/ARM/FromLLD/arm-adr-err-long.s @@ -3,7 +3,7 @@ // RUN: llvm-mc --triple=armv7a-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %t/asm // RUN: not %link --script %t/lds %t.o -o /dev/null 2>&1 | %filecheck %s -// FIXME: Only R_ARM_ALU_PC_G0 is enabled. +// FIXME: R_ARM_LDRS_PC_G2 is unsupported //--- lds SECTIONS { @@ -28,29 +28,29 @@ _start: .inst 0xe2400004 // sub r0, r0, #4 .reloc 0, R_ARM_ALU_PC_G0, dat1 // CHECK: Error: {{.*}}.o:(.text.1): unencodable immediate 7340040 for relocation 'R_ARM_ALU_PC_G0' referencing 'dat1 -// FIXME .reloc 4, R_ARM_ALU_PC_G1, dat1 + .reloc 4, R_ARM_ALU_PC_G1, dat1 .inst 0xe24f1008 // sub r1, pc, #8 .inst 0xe2411004 // sub r1, r1, #4 .inst 0xe2411000 // sub r1, r1, #0 -// FIXME .reloc 8, R_ARM_ALU_PC_G0_NC, dat2 -// FIXME .reloc 12, R_ARM_ALU_PC_G1, dat2 -// FIXME: {{.*}}.s.tmp.o:(.text.1+0xc): unencodeable immediate 244252656 for relocation R_ARM_ALU_PC_G1 -// FIXME .reloc 16, R_ARM_ALU_PC_G2, dat2 + .reloc 8, R_ARM_ALU_PC_G0_NC, dat2 + .reloc 12, R_ARM_ALU_PC_G1, dat2 +// CHECK: Error: {{.*}}.o:(.text.1+0xc): unencodable immediate 244252656 for relocation 'R_ARM_ALU_PC_G1' referencing 'dat2' + .reloc 16, R_ARM_ALU_PC_G2, dat2 .inst 0xe24f0008 // sub r0, pc, #8 .inst 0xe2400004 // sub r0, r0, #4 .inst 0xe2400000 // sub r0, r0, #0 .reloc 20, R_ARM_ALU_PC_G0, dat1 // CHECK: Error: {{.*}}.o:(.text.1+0x14): unencodable immediate 7340060 for relocation 'R_ARM_ALU_PC_G0' -// FIXME .reloc 24, R_ARM_ALU_PC_G1, dat1 -// FIXME .reloc 28, R_ARM_ALU_PC_G2, dat1 + .reloc 24, R_ARM_ALU_PC_G1, dat1 + .reloc 28, R_ARM_ALU_PC_G2, dat1 .inst 0xe24f0008 // sub r0, pc, #8 .inst 0xe2400004 // sub r0, r0, #4 .inst 0xe1c000d0 // ldrd r0, r1, [r0, #0] -// FIXME .reloc 32, R_ARM_ALU_PC_G0_NC, dat2 -// FIXME .reloc 36, R_ARM_ALU_PC_G1_NC, dat2 + .reloc 32, R_ARM_ALU_PC_G0_NC, dat2 + .reloc 36, R_ARM_ALU_PC_G1_NC, dat2 // FIXME: {{.*}}.s.tmp.o:(.text.1+0x28): relocation R_ARM_LDRS_PC_G2 out of range: 4056 is not in [0, 255]; references dat2 // FIXME .reloc 40, R_ARM_LDRS_PC_G2, dat2 diff --git a/test/ARM/FromLLD/arm-adr-long.s b/test/ARM/FromLLD/arm-adr-long.s new file mode 100644 index 0000000000..eace0c7116 --- /dev/null +++ b/test/ARM/FromLLD/arm-adr-long.s @@ -0,0 +1,105 @@ +// REQUIRES: arm +// RUN: split-file %s %t +// RUN: %llvm-mc --triple=armv7a-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %t/asm +// RUN: %link --script %t/lds %t.o -o %t2 +// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn --triple=armv7a-none-eabi %t2 | FileCheck %s + +// FIXME: R_ARM_LDR_PC_G1 and R_ARM_LDRS_PC_G1 is unsupported + +/// Test the long range encoding of R_ARM_ALU_PC_Gx sequences. We can encode an 8-bit +/// immediate rotated right by an even 4-bit field. + +//--- lds +SECTIONS { + .text.0 0x0100000 : AT(0x0100000) { *(.text.0) } + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0xf0f0000 : AT(0xf0f0000) { *(.text.2) } +} + +//--- asm + .section .text.0, "ax", %progbits +dat1: + .word 0 + + .section .text.1, "ax", %progbits + .global _start + .type _start, %function +_start: + .inst 0xe24f0008 // sub r0, pc, #8 + .inst 0xe2400004 // sub r0, r0, #4 + .reloc 0, R_ARM_ALU_PC_G0_NC, dat1 + .reloc 4, R_ARM_ALU_PC_G1, dat1 + + .inst 0xe24f1008 // sub r1, pc, #8 + .inst 0xe2411004 // sub r1, r1, #4 + .inst 0xe2411000 // sub r1, r1, #0 + .reloc 8, R_ARM_ALU_PC_G0_NC, dat2 + .reloc 12, R_ARM_ALU_PC_G1_NC, dat2 + .reloc 16, R_ARM_ALU_PC_G2, dat2 + + .inst 0xe24f0008 // sub r0, pc, #8 + .inst 0xe2400004 // sub r0, r0, #4 + .inst 0xe2400000 // sub r0, r0, #0 + .reloc 20, R_ARM_ALU_PC_G0_NC, dat1 + .reloc 24, R_ARM_ALU_PC_G1_NC, dat1 + .reloc 28, R_ARM_ALU_PC_G2, dat1 + + .inst 0xe24f0008 // sub r0, pc, #8 + .inst 0xe2400004 // sub r0, r0, #4 + .inst 0xe5900000 // ldr r0, [r0, #0] + .reloc 32, R_ARM_ALU_PC_G0_NC, dat2 + .reloc 36, R_ARM_ALU_PC_G1_NC, dat2 + .reloc 40, R_ARM_LDR_PC_G2, dat2 + + .inst 0xe24f0008 // sub r0, pc, #8 + .inst 0xe5100004 // ldr r0, [r0, #-4] + .reloc 44, R_ARM_ALU_PC_G0_NC, dat1 +// FIXME .reloc 48, R_ARM_LDR_PC_G1, dat1 + + .inst 0xe24f0008 // sub r0, pc, #8 + .inst 0xe2400004 // sub r0, r0, #4 + .inst 0xe5900000 // ldr r0, [r0, #0] + .reloc 52, R_ARM_ALU_PC_G0_NC, dat1 + .reloc 56, R_ARM_ALU_PC_G1_NC, dat1 + .reloc 60, R_ARM_LDR_PC_G2, dat1 + + .inst 0xe24f0008 // sub r0, pc, #8 + .inst 0xe14000d4 // ldrd r0, [r0, #-4] + .reloc 64, R_ARM_ALU_PC_G0_NC, dat1 +// FIXME .reloc 68, R_ARM_LDRS_PC_G1, dat1 + + .section .text.2, "ax", %progbits +dat2: + .word 0 + +// CHECK: 00100000 : +// CHECK-NEXT: 100000: andeq r0, r0, r0 + +// CHECK: 00800000 <_start>: +// CHECK-NEXT: 800000: sub r0, pc, #112, #16 +// CHECK-NEXT: 800004: sub r0, r0, #8 + +// CHECK-NEXT: 800008: add r1, pc, #232, #12 +// CHECK-NEXT: 80000c: add r1, r1, #978944 +// CHECK-NEXT: 800010: add r1, r1, #4080 + +// CHECK-NEXT: 800014: sub r0, pc, #112, #16 +// CHECK-NEXT: 800018: sub r0, r0, #28 +// CHECK-NEXT: 80001c: sub r0, r0, #0 + +// CHECK-NEXT: 800020: add r0, pc, #232, #12 +// CHECK-NEXT: 800024: add r0, r0, #978944 +// CHECK-NEXT: 800028: ldr r0, [r0, #4056] + +// CHECK-NEXT: 80002c: sub r0, pc, #112, #16 +// FIXME: 800030: ldr r0, [r0, #-52] + +// CHECK: 800034: sub r0, pc, #112, #16 +// CHECK-NEXT: 800038: sub r0, r0, #60 +// CHECK-NEXT: 80003c: ldr r0, [r0, #-0] + +// CHECK-NEXT: 800040: sub r0, pc, #112, #16 +// FIXME: 800044: ldrd r0, r1, [r0, #-72] + +// CHECK: 0f0f0000 : +// CHECK-NEXT: f0f0000: andeq r0, r0, r0 diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/1.s b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/1.s new file mode 100644 index 0000000000..4dbc76aeaa --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/1.s @@ -0,0 +1,13 @@ +.arm + +.section .text.1, "ax", %progbits +.space 0x28 +.global _start +.type _start, %function +_start: + add r0, r0, #0 + .reloc 0x28, R_ARM_ALU_PC_G0, dat2 + +.section .text.2, "ax", %progbits +dat2: + .word 0 diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/overflow.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/overflow.t new file mode 100644 index 0000000000..bded97b3ca --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/overflow.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x01700118 : AT(0x01700118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/valid.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/valid.t new file mode 100644 index 0000000000..66f6b9328c --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/valid.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x01700028 : AT(0x01700028) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/R_ARM_ALU_PC_G0.test b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/R_ARM_ALU_PC_G0.test new file mode 100644 index 0000000000..680c4ee93a --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/R_ARM_ALU_PC_G0.test @@ -0,0 +1,19 @@ +#---R_ARM_ALU_PC_G0.test--------------------- Executable ----------------------# +#BEGIN_COMMENT +# This tests that R_ARM_ALU_PC_G0 patches the ADD immediate (rotate + imm8) +# field with the group-0 residual and reports overflow when that residual +# does not fit. +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o +RUN: %link %linkopts -march arm -T %p/Inputs/valid.t %t1.1.o -o %t2.out +RUN: %objdump -d --triple=armv7a-none-eabi %t2.out | %filecheck %s --check-prefix=VALID + +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t3.1.o +RUN: %not %link %linkopts -march arm -T %p/Inputs/overflow.t %t3.1.o -o %t4.out 2>&1 | %filecheck %s --check-prefix=OVERFLOW + +#VALID: 00800028 <_start>: +#VALID-NEXT: 800028: e28008f0 add r0, r0, #240, #16 + +#OVERFLOW: Error: {{.*}}3.1.o:(.text.1+0x28): unencodable immediate 15728880 for relocation 'R_ARM_ALU_PC_G0' referencing 'dat2' +#END_TEST diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/1.s b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/1.s new file mode 100644 index 0000000000..885787ce40 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/1.s @@ -0,0 +1,13 @@ +.arm + +.section .text.1, "ax", %progbits +.space 0x28 +.global _start +.type _start, %function +_start: + add r0, r0, #0 + .reloc 0x28, R_ARM_ALU_PC_G0_NC, dat2 + +.section .text.2, "ax", %progbits +dat2: + .word 0 diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/overflow.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/overflow.t new file mode 100644 index 0000000000..bded97b3ca --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/overflow.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x01700118 : AT(0x01700118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/valid.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/valid.t new file mode 100644 index 0000000000..bded97b3ca --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/valid.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x01700118 : AT(0x01700118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/R_ARM_ALU_PC_G0_NC.test b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/R_ARM_ALU_PC_G0_NC.test new file mode 100644 index 0000000000..744e588531 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/R_ARM_ALU_PC_G0_NC.test @@ -0,0 +1,24 @@ +#---R_ARM_ALU_PC_G0_NC.test--------------------- Executable --------------------# +#BEGIN_COMMENT +# This tests that R_ARM_ALU_PC_G0_NC patches the ADD immediate (rotate + imm8) +# field with the group-0 residual and silently truncates a group-0 residual +# that does not fit the modified-immediate field instead of reporting an +# unencodable-immediate error. +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o +RUN: %link %linkopts -march arm -T %p/Inputs/valid.t %t1.1.o -o %t2.out +RUN: %objdump -d --triple=armv7a-none-eabi %t2.out | %filecheck %s --check-prefix=VALID + +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t3.1.o +RUN: %link %linkopts -march arm -T %p/Inputs/overflow.t %t3.1.o -o %t4.out 2>&1 | %filecheck %s --check-prefix=NOERROR --allow-empty +RUN: %objdump -d --triple=armv7a-none-eabi %t4.out | %filecheck %s --check-prefix=TRUNC + +#VALID: 00800028 <_start>: +#VALID-NEXT: 800028: e28008f0 add r0, r0, #240, #16 + +#NOERROR-NOT: unencodable immediate + +#TRUNC: 00800028 <_start>: +#TRUNC-NEXT: 800028: e28008f0 add r0, r0, #240, #16 +#END_TEST diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/1.s b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/1.s new file mode 100644 index 0000000000..d89341022c --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/1.s @@ -0,0 +1,13 @@ +.arm + +.section .text.1, "ax", %progbits +.space 0x28 +.global _start +.type _start, %function +_start: + add r0, r0, #0 + .reloc 0x28, R_ARM_ALU_PC_G1, dat2 + +.section .text.2, "ax", %progbits +dat2: + .word 0 diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/overflow.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/overflow.t new file mode 100644 index 0000000000..3416541319 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/overflow.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x0170f118 : AT(0x0170f118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/valid.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/valid.t new file mode 100644 index 0000000000..bded97b3ca --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/valid.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x01700118 : AT(0x01700118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/R_ARM_ALU_PC_G1.test b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/R_ARM_ALU_PC_G1.test new file mode 100644 index 0000000000..564617f4de --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/R_ARM_ALU_PC_G1.test @@ -0,0 +1,19 @@ +#---R_ARM_ALU_PC_G1.test--------------------- Executable ----------------------# +#BEGIN_COMMENT +# This tests that R_ARM_ALU_PC_G1 patches the ADD immediate (rotate + imm8) +# field with the group-1 residual and reports overflow when that residual +# does not fit. +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o +RUN: %link %linkopts -march arm -T %p/Inputs/valid.t %t1.1.o -o %t2.out +RUN: %objdump -d --triple=armv7a-none-eabi %t2.out | %filecheck %s --check-prefix=VALID + +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t3.1.o +RUN: %not %link %linkopts -march arm -T %p/Inputs/overflow.t %t3.1.o -o %t4.out 2>&1 | %filecheck %s --check-prefix=OVERFLOW + +#VALID: 00800028 <_start>: +#VALID-NEXT: 800028: e28000f0 add r0, r0, #240 + +#OVERFLOW: Error: {{.*}}3.1.o:(.text.1+0x28): unencodable immediate 15790320 for relocation 'R_ARM_ALU_PC_G1' referencing 'dat2' +#END_TEST diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/1.s b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/1.s new file mode 100644 index 0000000000..da5b7461c1 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/1.s @@ -0,0 +1,13 @@ +.arm + +.section .text.1, "ax", %progbits +.space 0x28 +.global _start +.type _start, %function +_start: + add r0, r0, #0 + .reloc 0x28, R_ARM_ALU_PC_G1_NC, dat2 + +.section .text.2, "ax", %progbits +dat2: + .word 0 diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/overflow.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/overflow.t new file mode 100644 index 0000000000..3416541319 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/overflow.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x0170f118 : AT(0x0170f118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/valid.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/valid.t new file mode 100644 index 0000000000..3416541319 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/Inputs/valid.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x0170f118 : AT(0x0170f118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/R_ARM_ALU_PC_G1_NC.test b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/R_ARM_ALU_PC_G1_NC.test new file mode 100644 index 0000000000..79cdb2f183 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1_NC/R_ARM_ALU_PC_G1_NC.test @@ -0,0 +1,24 @@ +#---R_ARM_ALU_PC_G1_NC.test--------------------- Executable -------------------# +#BEGIN_COMMENT +# This tests that R_ARM_ALU_PC_G1_NC patches the ADD immediate (rotate + imm8) +# field with the group-1 residual and silently truncates a group-1 residual +# that does not fit the modified-immediate field instead of reporting an +# unencodable-immediate error. +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o +RUN: %link %linkopts -march arm -T %p/Inputs/valid.t %t1.1.o -o %t2.out +RUN: %objdump -d --triple=armv7a-none-eabi %t2.out | %filecheck %s --check-prefix=VALID + +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t3.1.o +RUN: %link %linkopts -march arm -T %p/Inputs/overflow.t %t3.1.o -o %t4.out 2>&1 | %filecheck %s --check-prefix=NOERROR --allow-empty +RUN: %objdump -d --triple=armv7a-none-eabi %t4.out | %filecheck %s --check-prefix=TRUNC + +#VALID: 00800028 <_start>: +#VALID-NEXT: 800028: e2800cf0 add r0, r0, #240, #24 + +#NOERROR-NOT: unencodable immediate + +#TRUNC: 00800028 <_start>: +#TRUNC-NEXT: 800028: e2800cf0 add r0, r0, #240, #24 +#END_TEST diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/1.s b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/1.s new file mode 100644 index 0000000000..9aa9e347b8 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/1.s @@ -0,0 +1,13 @@ +.arm + +.section .text.1, "ax", %progbits +.space 0x28 +.global _start +.type _start, %function +_start: + add r0, r0, #0 + .reloc 0x28, R_ARM_ALU_PC_G2, dat2 + +.section .text.2, "ax", %progbits +dat2: + .word 0 diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/overflow.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/overflow.t new file mode 100644 index 0000000000..e1c67e9985 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/overflow.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x0f8f0f37 : AT(0x0f8f0f37) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/valid.t b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/valid.t new file mode 100644 index 0000000000..3416541319 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/Inputs/valid.t @@ -0,0 +1,4 @@ +SECTIONS { + .text.1 0x0800000 : AT(0x0800000) { *(.text.1) } + .text.2 0x0170f118 : AT(0x0170f118) { *(.text.2) } +} diff --git a/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/R_ARM_ALU_PC_G2.test b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/R_ARM_ALU_PC_G2.test new file mode 100644 index 0000000000..34b0bfdb09 --- /dev/null +++ b/test/ARM/standalone/Relocs/R_ARM_ALU_PC_G2/R_ARM_ALU_PC_G2.test @@ -0,0 +1,19 @@ +#---R_ARM_ALU_PC_G2.test--------------------- Executable ----------------------# +#BEGIN_COMMENT +# This tests that R_ARM_ALU_PC_G2 patches the ADD immediate (rotate + imm8) +# field with the group-2 residual and reports overflow when that residual +# does not fit. +#END_COMMENT +#START_TEST +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o +RUN: %link %linkopts -march arm -T %p/Inputs/valid.t %t1.1.o -o %t2.out +RUN: %objdump -d --triple=armv7a-none-eabi %t2.out | %filecheck %s --check-prefix=VALID + +RUN: %clang %clangopts -c %p/Inputs/1.s -o %t3.1.o +RUN: %not %link %linkopts -march arm -T %p/Inputs/overflow.t %t3.1.o -o %t4.out 2>&1 | %filecheck %s --check-prefix=OVERFLOW + +#VALID: 00800028 <_start>: +#VALID-NEXT: 800028: e28000f0 add r0, r0, #240 + +#OVERFLOW: Error: {{.*}}3.1.o:(.text.1+0x28): unencodable immediate 252645135 for relocation 'R_ARM_ALU_PC_G2' referencing 'dat2' +#END_TEST