[lld] [LLD][ELF][ARM] Fix resolution of R_ARM_THM_JUMP8 and R_ARM_THM_JUMP11 (PR #126933)
Victor Campos via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 13 09:21:45 PST 2025
https://github.com/vhscampos updated https://github.com/llvm/llvm-project/pull/126933
>From f6c2ea52ffec21be7d76a523d3f7792ae377a6f7 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Wed, 12 Feb 2025 09:51:45 +0000
Subject: [PATCH 1/5] [LLD][ELF][ARM] Fix resolution of R_ARM_THM_JUMP8 and
R_ARM_THM_JUMP11
These relocations apply to 16-bit Thumb instructions, so reading 16 bits
rather than 32 bits ensures the correct bits are masked and written
back. This fixes the incorrect masking and aligns the relocation logic
with the instruction encoding.
Before this patch, 32 bits were read from the ELF object. This did not
align with the instruction size of 16 bits, but the masking incidentally
made it all work nonetheless. However, this was the case only in little
endian.
In big endian mode, the read 32-bit word had to have its bytes reversed.
With this byte reordering, the masking would be applied to the wrong
bits, hence causing the incorrect encoding to be produced as a result of
the relocation resolution.
The added test checks the result for both little and big endian modes.
For the sake of deduplication of test files, the single test file makes
use of the preprocessor and `split-file` to fit all the required logic
into it.
---
lld/ELF/Arch/ARM.cpp | 4 +-
lld/test/ELF/arm-thumb-jump8-11.test | 108 +++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 2 deletions(-)
create mode 100644 lld/test/ELF/arm-thumb-jump8-11.test
diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index 7d2953ddf64f0..e667fdc0633c5 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -663,12 +663,12 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_ARM_THM_JUMP8:
// We do a 9 bit check because val is right-shifted by 1 bit.
checkInt(ctx, loc, val, 9, rel);
- write16(ctx, loc, (read32(ctx, loc) & 0xff00) | ((val >> 1) & 0x00ff));
+ write16(ctx, loc, (read16(ctx, loc) & 0xff00) | ((val >> 1) & 0x00ff));
break;
case R_ARM_THM_JUMP11:
// We do a 12 bit check because val is right-shifted by 1 bit.
checkInt(ctx, loc, val, 12, rel);
- write16(ctx, loc, (read32(ctx, loc) & 0xf800) | ((val >> 1) & 0x07ff));
+ write16(ctx, loc, (read16(ctx, loc) & 0xf800) | ((val >> 1) & 0x07ff));
break;
case R_ARM_THM_JUMP19:
// Encoding T3: Val = S:J2:J1:imm6:imm11:0
diff --git a/lld/test/ELF/arm-thumb-jump8-11.test b/lld/test/ELF/arm-thumb-jump8-11.test
new file mode 100644
index 0000000000000..0c9ef689be24d
--- /dev/null
+++ b/lld/test/ELF/arm-thumb-jump8-11.test
@@ -0,0 +1,108 @@
+# RUN: split-file %s %t
+# RUN: clang -x c -E -P -DLITTLEENDIAN %t/a.yaml -o %t/a.yaml
+# RUN: clang -x c -E -P -DLITTLEENDIAN %t/b.yaml -o %t/b.yaml
+# RUN: yaml2obj %t/a.yaml -o %t/a.o
+# RUN: yaml2obj %t/b.yaml -o %t/b.o
+# RUN: ld.lld %t/a.o %t/b.o -o %t/linked.o
+# RUN: llvm-objdump -d %t/linked.o | FileCheck %s --check-prefixes=CHECK,CHECK-LE
+
+# RUN: split-file %s %t
+# RUN: clang -x c -E -P -DBIGENDIAN %t/a.yaml -o %t/a.yaml
+# RUN: clang -x c -E -P -DBIGENDIAN %t/b.yaml -o %t/b.yaml
+# RUN: yaml2obj %t/a.yaml -o %t/a.o
+# RUN: yaml2obj %t/b.yaml -o %t/b.o
+# RUN: ld.lld %t/a.o %t/b.o -o %t/linked.o
+# RUN: llvm-objdump -d %t/linked.o | FileCheck %s --check-prefixes=CHECK,CHECK-BE
+
+# CHECK-LE: linked.o: file format elf32-littlearm
+# CHECK-BE: linked.o: file format elf32-bigarm
+# CHECK-EMPTY:
+# CHECK-NEXT: Disassembly of section .text:
+# CHECK-EMPTY:
+# CHECK-NEXT: [[#%x,_START:]] <_start>:
+# CHECK-NEXT: [[#_START]]: e000 b 0x[[FOO:[0-9a-f]+]] <foo> @ imm = #0x0
+# CHECK-NEXT: [[#_START+2]]: d0ff beq 0x[[FOO]] <foo> @ imm = #-0x2
+# CHECK-EMPTY:
+# CHECK-NEXT: [[#_START+4]] <foo>:
+# CHECK-NEXT: [[#_START+4]]: 4770 bx lr
+
+#--- a.yaml
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+#if defined BIGENDIAN
+ Data: ELFDATA2MSB
+#elif defined LITTLEENDIAN
+ Data: ELFDATA2LSB
+#endif
+ Type: ET_REL
+ Machine: EM_ARM
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+#if defined BIGENDIAN
+ Content: E7FED0FE
+#elif defined LITTLEENDIAN
+ Content: FEE7FED0
+#endif
+ - Name: .rel.text
+ Type: SHT_REL
+ Info: .text
+ Relocations:
+ - Symbol: foo
+ Type: R_ARM_THM_JUMP11
+ - Offset: 0x2
+ Symbol: foo
+ Type: R_ARM_THM_JUMP8
+Symbols:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ - Name: '$t'
+ Section: .text
+ - Name: _start
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1
+ Size: 0x4
+ - Name: foo
+ Binding: STB_GLOBAL
+...
+
+#--- b.yaml
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+#if defined BIGENDIAN
+ Data: ELFDATA2MSB
+#elif defined LITTLEENDIAN
+ Data: ELFDATA2LSB
+#endif
+ Type: ET_REL
+ Machine: EM_ARM
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+#ifdef BIGENDIAN
+ Content: '4770'
+#elif defined LITTLEENDIAN
+ Content: '7047'
+#endif
+Symbols:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ - Name: '$t'
+ Section: .text
+ - Name: foo
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1
+ Size: 0x2
+...
>From 4ad0f9511b1be803a512d8f1726a6b3e8a64fd1b Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Wed, 12 Feb 2025 16:08:36 +0000
Subject: [PATCH 2/5] Fix indentation in the test
---
lld/test/ELF/arm-thumb-jump8-11.test | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lld/test/ELF/arm-thumb-jump8-11.test b/lld/test/ELF/arm-thumb-jump8-11.test
index 0c9ef689be24d..021a26c38e794 100644
--- a/lld/test/ELF/arm-thumb-jump8-11.test
+++ b/lld/test/ELF/arm-thumb-jump8-11.test
@@ -14,17 +14,17 @@
# RUN: ld.lld %t/a.o %t/b.o -o %t/linked.o
# RUN: llvm-objdump -d %t/linked.o | FileCheck %s --check-prefixes=CHECK,CHECK-BE
-# CHECK-LE: linked.o: file format elf32-littlearm
-# CHECK-BE: linked.o: file format elf32-bigarm
+# CHECK-LE: linked.o: file format elf32-littlearm
+# CHECK-BE: linked.o: file format elf32-bigarm
# CHECK-EMPTY:
# CHECK-NEXT: Disassembly of section .text:
# CHECK-EMPTY:
# CHECK-NEXT: [[#%x,_START:]] <_start>:
-# CHECK-NEXT: [[#_START]]: e000 b 0x[[FOO:[0-9a-f]+]] <foo> @ imm = #0x0
-# CHECK-NEXT: [[#_START+2]]: d0ff beq 0x[[FOO]] <foo> @ imm = #-0x2
+# CHECK-NEXT: [[#_START]]: e000 b 0x[[FOO:[0-9a-f]+]] <foo> @ imm = #0x0
+# CHECK-NEXT: [[#_START+2]]: d0ff beq 0x[[FOO]] <foo> @ imm = #-0x2
# CHECK-EMPTY:
# CHECK-NEXT: [[#_START+4]] <foo>:
-# CHECK-NEXT: [[#_START+4]]: 4770 bx lr
+# CHECK-NEXT: [[#_START+4]]: 4770 bx lr
#--- a.yaml
>From c91f8403793ad1173e9e194d762c8f5fe7728c62 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 13 Feb 2025 10:52:49 +0000
Subject: [PATCH 3/5] Simplify testcase by using the assembler
---
lld/test/ELF/arm-thumb-jump8-11.s | 30 ++++++++
lld/test/ELF/arm-thumb-jump8-11.test | 108 ---------------------------
2 files changed, 30 insertions(+), 108 deletions(-)
create mode 100644 lld/test/ELF/arm-thumb-jump8-11.s
delete mode 100644 lld/test/ELF/arm-thumb-jump8-11.test
diff --git a/lld/test/ELF/arm-thumb-jump8-11.s b/lld/test/ELF/arm-thumb-jump8-11.s
new file mode 100644
index 0000000000000..f34c621591882
--- /dev/null
+++ b/lld/test/ELF/arm-thumb-jump8-11.s
@@ -0,0 +1,30 @@
+# RUN: llvm-mc -triple thumbv6m-arm-eabi --filetype=obj %s -o %t.obj
+# RUN: ld.lld %t.obj -o %t.linked
+# RUN: llvm-objdump -d %t.linked | FileCheck %s --check-prefixes=CHECK,CHECK-LE
+
+# RUN: llvm-mc -triple thumbebv6m-arm-eabi --filetype=obj %s -o %t.obj
+# RUN: ld.lld %t.obj -o %t.linked
+# RUN: llvm-objdump -d %t.linked | FileCheck %s --check-prefixes=CHECK,CHECK-BE
+
+# CHECK-LE: file format elf32-littlearm
+# CHECK-BE: file format elf32-bigarm
+
+# CHECK: Disassembly of section .text:
+
+# CHECK-LABEL: [[#%x,TARGET:]] <target>:
+# CHECK-NEXT: [[#TARGET]]: 4770 bx lr
+
+# CHECK-LABEL: <_start>:
+# CHECK-NEXT: e7fd b 0x[[#TARGET]] <target>
+# CHECK-NEXT: d0fc beq 0x[[#TARGET]] <target>
+
+ .thumb
+ .section .text.1, "ax", %progbits
+target:
+ bx lr
+
+ .section .text.2, "ax", %progbits
+ .globl _start
+_start:
+ b.n target // R_ARM_THM_JUMP11
+ beq.n target // R_ARM_THM_JUMP8
diff --git a/lld/test/ELF/arm-thumb-jump8-11.test b/lld/test/ELF/arm-thumb-jump8-11.test
deleted file mode 100644
index 021a26c38e794..0000000000000
--- a/lld/test/ELF/arm-thumb-jump8-11.test
+++ /dev/null
@@ -1,108 +0,0 @@
-# RUN: split-file %s %t
-# RUN: clang -x c -E -P -DLITTLEENDIAN %t/a.yaml -o %t/a.yaml
-# RUN: clang -x c -E -P -DLITTLEENDIAN %t/b.yaml -o %t/b.yaml
-# RUN: yaml2obj %t/a.yaml -o %t/a.o
-# RUN: yaml2obj %t/b.yaml -o %t/b.o
-# RUN: ld.lld %t/a.o %t/b.o -o %t/linked.o
-# RUN: llvm-objdump -d %t/linked.o | FileCheck %s --check-prefixes=CHECK,CHECK-LE
-
-# RUN: split-file %s %t
-# RUN: clang -x c -E -P -DBIGENDIAN %t/a.yaml -o %t/a.yaml
-# RUN: clang -x c -E -P -DBIGENDIAN %t/b.yaml -o %t/b.yaml
-# RUN: yaml2obj %t/a.yaml -o %t/a.o
-# RUN: yaml2obj %t/b.yaml -o %t/b.o
-# RUN: ld.lld %t/a.o %t/b.o -o %t/linked.o
-# RUN: llvm-objdump -d %t/linked.o | FileCheck %s --check-prefixes=CHECK,CHECK-BE
-
-# CHECK-LE: linked.o: file format elf32-littlearm
-# CHECK-BE: linked.o: file format elf32-bigarm
-# CHECK-EMPTY:
-# CHECK-NEXT: Disassembly of section .text:
-# CHECK-EMPTY:
-# CHECK-NEXT: [[#%x,_START:]] <_start>:
-# CHECK-NEXT: [[#_START]]: e000 b 0x[[FOO:[0-9a-f]+]] <foo> @ imm = #0x0
-# CHECK-NEXT: [[#_START+2]]: d0ff beq 0x[[FOO]] <foo> @ imm = #-0x2
-# CHECK-EMPTY:
-# CHECK-NEXT: [[#_START+4]] <foo>:
-# CHECK-NEXT: [[#_START+4]]: 4770 bx lr
-
-#--- a.yaml
-
---- !ELF
-FileHeader:
- Class: ELFCLASS32
-#if defined BIGENDIAN
- Data: ELFDATA2MSB
-#elif defined LITTLEENDIAN
- Data: ELFDATA2LSB
-#endif
- Type: ET_REL
- Machine: EM_ARM
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-#if defined BIGENDIAN
- Content: E7FED0FE
-#elif defined LITTLEENDIAN
- Content: FEE7FED0
-#endif
- - Name: .rel.text
- Type: SHT_REL
- Info: .text
- Relocations:
- - Symbol: foo
- Type: R_ARM_THM_JUMP11
- - Offset: 0x2
- Symbol: foo
- Type: R_ARM_THM_JUMP8
-Symbols:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: '$t'
- Section: .text
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x1
- Size: 0x4
- - Name: foo
- Binding: STB_GLOBAL
-...
-
-#--- b.yaml
-
---- !ELF
-FileHeader:
- Class: ELFCLASS32
-#if defined BIGENDIAN
- Data: ELFDATA2MSB
-#elif defined LITTLEENDIAN
- Data: ELFDATA2LSB
-#endif
- Type: ET_REL
- Machine: EM_ARM
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-#ifdef BIGENDIAN
- Content: '4770'
-#elif defined LITTLEENDIAN
- Content: '7047'
-#endif
-Symbols:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: '$t'
- Section: .text
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x1
- Size: 0x2
-...
>From 6db812260720bfedabe65a795f9a436e3043a622 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 13 Feb 2025 11:32:57 +0000
Subject: [PATCH 4/5] Add REQUIRES: arm
---
lld/test/ELF/arm-thumb-jump8-11.s | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lld/test/ELF/arm-thumb-jump8-11.s b/lld/test/ELF/arm-thumb-jump8-11.s
index f34c621591882..4ed1d736f082e 100644
--- a/lld/test/ELF/arm-thumb-jump8-11.s
+++ b/lld/test/ELF/arm-thumb-jump8-11.s
@@ -1,3 +1,5 @@
+# REQUIRES: arm
+
# RUN: llvm-mc -triple thumbv6m-arm-eabi --filetype=obj %s -o %t.obj
# RUN: ld.lld %t.obj -o %t.linked
# RUN: llvm-objdump -d %t.linked | FileCheck %s --check-prefixes=CHECK,CHECK-LE
>From a67c49502f86caf4f262f505804887fb2021fc94 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 13 Feb 2025 17:18:13 +0000
Subject: [PATCH 5/5] Address comments
---
lld/test/ELF/arm-thumb-jump8-11.s | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/lld/test/ELF/arm-thumb-jump8-11.s b/lld/test/ELF/arm-thumb-jump8-11.s
index 4ed1d736f082e..ed54f3c0cc945 100644
--- a/lld/test/ELF/arm-thumb-jump8-11.s
+++ b/lld/test/ELF/arm-thumb-jump8-11.s
@@ -1,12 +1,12 @@
# REQUIRES: arm
-# RUN: llvm-mc -triple thumbv6m-arm-eabi --filetype=obj %s -o %t.obj
-# RUN: ld.lld %t.obj -o %t.linked
-# RUN: llvm-objdump -d %t.linked | FileCheck %s --check-prefixes=CHECK,CHECK-LE
+# RUN: llvm-mc -triple thumbv6m-arm-eabi --filetype=obj %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -d %t --no-show-raw-insn | FileCheck %s --check-prefixes=CHECK,CHECK-LE
-# RUN: llvm-mc -triple thumbebv6m-arm-eabi --filetype=obj %s -o %t.obj
-# RUN: ld.lld %t.obj -o %t.linked
-# RUN: llvm-objdump -d %t.linked | FileCheck %s --check-prefixes=CHECK,CHECK-BE
+# RUN: llvm-mc -triple thumbebv6m-arm-eabi --filetype=obj %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -d %t --no-show-raw-insn | FileCheck %s --check-prefixes=CHECK,CHECK-BE
# CHECK-LE: file format elf32-littlearm
# CHECK-BE: file format elf32-bigarm
@@ -14,17 +14,17 @@
# CHECK: Disassembly of section .text:
# CHECK-LABEL: [[#%x,TARGET:]] <target>:
-# CHECK-NEXT: [[#TARGET]]: 4770 bx lr
+# CHECK-NEXT: [[#TARGET]]: bx lr
# CHECK-LABEL: <_start>:
-# CHECK-NEXT: e7fd b 0x[[#TARGET]] <target>
-# CHECK-NEXT: d0fc beq 0x[[#TARGET]] <target>
+# CHECK-NEXT: b 0x[[#TARGET]] <target>
+# CHECK-NEXT: beq 0x[[#TARGET]] <target>
.thumb
.section .text.1, "ax", %progbits
target:
bx lr
-
+
.section .text.2, "ax", %progbits
.globl _start
_start:
More information about the llvm-commits
mailing list