[lld] lld/AArch64: handle more relocation addends (PR #87328)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 10 05:29:15 PDT 2024


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/87328

>From 9d2097f9d60d2a9fc501685c3a5c75214f586cd4 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ram.ramachandra at arm.com>
Date: Thu, 28 Mar 2024 18:02:29 +0000
Subject: [PATCH 1/3] lld/AArch64: handle more relocation addends

The function getImplicitAddend() is incomplete, as it is possible to
cook up object files with other relocation addends. Although using
llvm-mc or the clang integrated assembler does not produce such object
files, a proprietary assembler known as armasm can:

  https://developer.arm.com/documentation/101754/0622/armasm-Legacy-Assembler-Reference

armasm is in a frozen state, but it is still actively used in a lot of
legacy codebases as the directives, macros and operators are very
different from the clang integrated assembler. This makes porting a lot
of legacy code from armasm syntax impractical for a lot of projects.
Some internal testing of projects using open-source clang and lld fell
over at link time when legacy armasm objects were included in the link.

The goal of this patch is to enable people with legacy armasm objects to
be able to use lld as the linker. Sadly armasm uses SHT_REL format
relocations for AArch64 rather than SHT_RELA, which causes lld to reject
the objects. As a frozen project we know the small number of relocations
that the assembler officially supports and won't include (outside the
equivalent of the .reloc directive which I think we can rule out of
scope as that is not commonly used).

The benefit to lld is that it will ease migration from a proprietary to
an open-source toolchain. The drawback is the implementation of a small
number of SHT_REL relocations. Although this patch doesn't aim to
comprehensively cover all possible relocation addends, it does extend
lld to work with the relocation addends that armasm produces, using the
canonical aaelf64 document as a reference:

  https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst
---
 lld/ELF/Arch/AArch64.cpp                      | 42 +++++++++++++++----
 .../ELF/aarch64-reloc-implicit-addend.test    |  8 +++-
 2 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 017c17c2b03d83..2bf6e2c6c85195 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -69,6 +69,13 @@ struct AArch64Relaxer {
 };
 } // namespace
 
+// Return the bits [Start, End] from Val shifted Start bits.
+// For instance, getBits(0xF0, 4, 8) returns 0xF.
+static uint64_t getBits(uint64_t val, int start, int end) {
+  uint64_t mask = ((uint64_t)1 << (end + 1 - start)) - 1;
+  return (val >> start) & mask;
+}
+
 AArch64::AArch64() {
   copyRel = R_AARCH64_COPY;
   relativeRel = R_AARCH64_RELATIVE;
@@ -219,6 +226,10 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_AARCH64_GLOB_DAT:
   case R_AARCH64_JUMP_SLOT:
     return 0;
+  case R_AARCH64_ABS16:
+  case R_AARCH64_PREL16:
+    return SignExtend64<16>(read16(buf));
+  case R_AARCH64_ABS32:
   case R_AARCH64_PREL32:
     return SignExtend64<32>(read32(buf));
   case R_AARCH64_ABS64:
@@ -227,6 +238,30 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_AARCH64_IRELATIVE:
   case R_AARCH64_TLS_TPREL64:
     return read64(buf);
+  case R_AARCH64_MOVW_UABS_G0:
+  case R_AARCH64_MOVW_UABS_G0_NC:
+    return getBits(SignExtend64<16>(read16(buf)), 0, 15);
+  case R_AARCH64_MOVW_UABS_G1:
+  case R_AARCH64_MOVW_UABS_G1_NC:
+    return getBits(SignExtend64<32>(read32(buf)), 16, 31);
+  case R_AARCH64_MOVW_UABS_G2:
+  case R_AARCH64_MOVW_UABS_G2_NC:
+    return getBits(read64(buf), 32, 47);
+  case R_AARCH64_MOVW_UABS_G3:
+    return getBits(read64(buf), 48, 63);
+  case R_AARCH64_TSTBR14:
+    return getBits(SignExtend64<32>(read32(buf)), 2, 15);
+  case R_AARCH64_CONDBR19:
+  case R_AARCH64_LD_PREL_LO19:
+    return getBits(SignExtend64<32>(read32(buf)), 2, 20);
+  case R_AARCH64_ADD_ABS_LO12_NC:
+    return getBits(SignExtend64<16>(read16(buf)), 0, 11);
+  case R_AARCH64_ADR_PREL_PG_HI21:
+  case R_AARCH64_ADR_PREL_PG_HI21_NC:
+    return getBits(SignExtend64<32>(read32(buf)), 12, 32);
+  case R_AARCH64_JUMP26:
+  case R_AARCH64_CALL26:
+    return getBits(SignExtend64<32>(read32(buf)), 2, 27);
   default:
     internalLinkerError(getErrorLocation(buf),
                         "cannot read addend for relocation " + toString(type));
@@ -330,13 +365,6 @@ static void write32AArch64Addr(uint8_t *l, uint64_t imm) {
   write32le(l, (read32le(l) & ~mask) | immLo | immHi);
 }
 
-// Return the bits [Start, End] from Val shifted Start bits.
-// For instance, getBits(0xF0, 4, 8) returns 0xF.
-static uint64_t getBits(uint64_t val, int start, int end) {
-  uint64_t mask = ((uint64_t)1 << (end + 1 - start)) - 1;
-  return (val >> start) & mask;
-}
-
 static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); }
 
 // Update the immediate field in a AARCH64 ldr, str, and add instruction.
diff --git a/lld/test/ELF/aarch64-reloc-implicit-addend.test b/lld/test/ELF/aarch64-reloc-implicit-addend.test
index 15f42c4d87b577..c71ca1e3be56fc 100644
--- a/lld/test/ELF/aarch64-reloc-implicit-addend.test
+++ b/lld/test/ELF/aarch64-reloc-implicit-addend.test
@@ -1,8 +1,12 @@
 ## Test certain REL relocation types generated by legacy armasm.
 # RUN: yaml2obj %s -o %t.o
-# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
+# RUN: ld.lld %t.o -o %t.out
+# RUN: llvm-objdump -t %t.out | FileCheck %s
 
-# CHECK-COUNT-17: internal linker error: cannot read addend
+# CHECK:      SYMBOL TABLE:
+# CHECK-NEXT: 0000000000200130 l       .branch	0000000000000000 .branch
+# CHECK-NEXT: 0000000000200118 l       .prel	0000000000000000 .prel
+# CHECK-NEXT: 000000000000002a g       *ABS*	0000000000000000 abs
 
 ---
 !ELF

>From 3397a55fa99b6d2997183cd9c62925442f69817f Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ram.ramachandra at arm.com>
Date: Sat, 6 Apr 2024 12:29:32 +0100
Subject: [PATCH 2/3] lld/ELF/test: address review; use objdump -s

---
 .../ELF/aarch64-reloc-implicit-addend.test    | 36 +++++++++++++++----
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/lld/test/ELF/aarch64-reloc-implicit-addend.test b/lld/test/ELF/aarch64-reloc-implicit-addend.test
index c71ca1e3be56fc..0d3928b60d5b96 100644
--- a/lld/test/ELF/aarch64-reloc-implicit-addend.test
+++ b/lld/test/ELF/aarch64-reloc-implicit-addend.test
@@ -1,12 +1,36 @@
 ## Test certain REL relocation types generated by legacy armasm.
 # RUN: yaml2obj %s -o %t.o
-# RUN: ld.lld %t.o -o %t.out
-# RUN: llvm-objdump -t %t.out | FileCheck %s
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -s %t | FileCheck %s
 
-# CHECK:      SYMBOL TABLE:
-# CHECK-NEXT: 0000000000200130 l       .branch	0000000000000000 .branch
-# CHECK-NEXT: 0000000000200118 l       .prel	0000000000000000 .prel
-# CHECK-NEXT: 000000000000002a g       *ABS*	0000000000000000 abs
+# CHECK:      Contents of section .abs:
+# CHECK-NEXT:  2000e8 29002800 00002700 00000000 0000fcff  ).(...'.........
+# CHECK-NEXT:  2000f8 ffffffff ffff                        ......
+# CHECK-NEXT: Contents of section .uabs:
+# CHECK-NEXT:  200100 40ffffff 40ffffff 20ffffff 20ffffff  @... at ... ... ...
+# CHECK-NEXT:  200110 00ffffff 00ffffff                    ........
+# CHECK-NEXT: Contents of section .prel:
+# CHECK-NEXT:  200118 00ffffff fcfeffff f8feffff a0ffffff  ................
+# CHECK-NEXT:  200128 0010009f 0010009f                    ........
+# CHECK-NEXT: Contents of section .branch:
+# CHECK-NEXT:  200130 f0ffffff f0ffffff fdffffff fcffff14  ................
+# CHECK-NEXT: Contents of section .comment:
+# CHECK-NEXT:  0000 4c4c4420 312e3000                    LLD 1.0.
+# CHECK-NEXT: Contents of section .symtab:
+# CHECK-NEXT:  0000 00000000 00000000 00000000 00000000  ................
+# CHECK-NEXT:  0010 00000000 00000000 01000000 00000400  ................
+# CHECK-NEXT:  0020 30012000 00000000 00000000 00000000  0. .............
+# CHECK-NEXT:  0030 09000000 00000300 18012000 00000000  .......... .....
+# CHECK-NEXT:  0040 00000000 00000000 0f000000 1000f1ff  ................
+# CHECK-NEXT:  0050 2a000000 00000000 00000000 00000000  *...............
+# CHECK-NEXT: Contents of section .shstrtab:
+# CHECK-NEXT:  0000 002e6162 73002e75 61627300 2e707265  ..abs..uabs..pre
+# CHECK-NEXT:  0010 6c002e62 72616e63 68002e63 6f6d6d65  l..branch..comme
+# CHECK-NEXT:  0020 6e74002e 73796d74 6162002e 73687374  nt..symtab..shst
+# CHECK-NEXT:  0030 72746162 002e7374 72746162 00        rtab..strtab.
+# CHECK-NEXT: Contents of section .strtab:
+# CHECK-NEXT:  0000 002e6272 616e6368 002e7072 656c0061  ..branch..prel.a
+# CHECK-NEXT:  0010 627300                               bs.
 
 ---
 !ELF

>From bc6b8df707922f26c6a8527dd6bf976268555554 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ram.ramachandra at arm.com>
Date: Wed, 10 Apr 2024 12:53:04 +0100
Subject: [PATCH 3/3] lld/ELF/test: address review

---
 .../ELF/aarch64-reloc-implicit-addend.test    | 31 +++++--------------
 1 file changed, 7 insertions(+), 24 deletions(-)

diff --git a/lld/test/ELF/aarch64-reloc-implicit-addend.test b/lld/test/ELF/aarch64-reloc-implicit-addend.test
index 0d3928b60d5b96..804ed97a273714 100644
--- a/lld/test/ELF/aarch64-reloc-implicit-addend.test
+++ b/lld/test/ELF/aarch64-reloc-implicit-addend.test
@@ -4,33 +4,16 @@
 # RUN: llvm-objdump -s %t | FileCheck %s
 
 # CHECK:      Contents of section .abs:
-# CHECK-NEXT:  2000e8 29002800 00002700 00000000 0000fcff  ).(...'.........
-# CHECK-NEXT:  2000f8 ffffffff ffff                        ......
+# CHECK-NEXT:  [[#%x,]] 29002800 00002700 00000000 0000fcff  ).(...'.........
+# CHECK-NEXT:  [[#%x,]] ffffffff ffff                        ......
 # CHECK-NEXT: Contents of section .uabs:
-# CHECK-NEXT:  200100 40ffffff 40ffffff 20ffffff 20ffffff  @... at ... ... ...
-# CHECK-NEXT:  200110 00ffffff 00ffffff                    ........
+# CHECK-NEXT:  [[#%x,]] 40ffffff 40ffffff 20ffffff 20ffffff  @... at ... ... ...
+# CHECK-NEXT:  [[#%x,]] 00ffffff 00ffffff                    ........
 # CHECK-NEXT: Contents of section .prel:
-# CHECK-NEXT:  200118 00ffffff fcfeffff f8feffff a0ffffff  ................
-# CHECK-NEXT:  200128 0010009f 0010009f                    ........
+# CHECK-NEXT:  [[#%x,]] 00ffffff fcfeffff f8feffff a0ffffff  ................
+# CHECK-NEXT:  [[#%x,]] 0010009f 0010009f                    ........
 # CHECK-NEXT: Contents of section .branch:
-# CHECK-NEXT:  200130 f0ffffff f0ffffff fdffffff fcffff14  ................
-# CHECK-NEXT: Contents of section .comment:
-# CHECK-NEXT:  0000 4c4c4420 312e3000                    LLD 1.0.
-# CHECK-NEXT: Contents of section .symtab:
-# CHECK-NEXT:  0000 00000000 00000000 00000000 00000000  ................
-# CHECK-NEXT:  0010 00000000 00000000 01000000 00000400  ................
-# CHECK-NEXT:  0020 30012000 00000000 00000000 00000000  0. .............
-# CHECK-NEXT:  0030 09000000 00000300 18012000 00000000  .......... .....
-# CHECK-NEXT:  0040 00000000 00000000 0f000000 1000f1ff  ................
-# CHECK-NEXT:  0050 2a000000 00000000 00000000 00000000  *...............
-# CHECK-NEXT: Contents of section .shstrtab:
-# CHECK-NEXT:  0000 002e6162 73002e75 61627300 2e707265  ..abs..uabs..pre
-# CHECK-NEXT:  0010 6c002e62 72616e63 68002e63 6f6d6d65  l..branch..comme
-# CHECK-NEXT:  0020 6e74002e 73796d74 6162002e 73687374  nt..symtab..shst
-# CHECK-NEXT:  0030 72746162 002e7374 72746162 00        rtab..strtab.
-# CHECK-NEXT: Contents of section .strtab:
-# CHECK-NEXT:  0000 002e6272 616e6368 002e7072 656c0061  ..branch..prel.a
-# CHECK-NEXT:  0010 627300                               bs.
+# CHECK-NEXT:  [[#%x,]] f0ffffff f0ffffff fdffffff fcffff14  ................
 
 ---
 !ELF



More information about the llvm-commits mailing list