[lld] aff950e - [ELF] Support a few more SPARCv9 relocations

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 08:14:17 PDT 2020


Author: LemonBoy
Date: 2020-04-17T08:12:15-07:00
New Revision: aff950e95d4a0b09fa8629e7358e5e06ea2ceb87

URL: https://github.com/llvm/llvm-project/commit/aff950e95d4a0b09fa8629e7358e5e06ea2ceb87
DIFF: https://github.com/llvm/llvm-project/commit/aff950e95d4a0b09fa8629e7358e5e06ea2ceb87.diff

LOG: [ELF] Support a few more SPARCv9 relocations

Implemented a bunch of relocations found in binaries with medium/large code model and the Local-Exec TLS model. The binaries link and run fine in Qemu.
In addition, the emulation `elf64_sparc` is now recognized.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D77672

Added: 
    lld/test/ELF/emulation-sparc.s
    lld/test/ELF/sparcv9-reloc.s
    lld/test/ELF/sparcv9-tls-le.s

Modified: 
    lld/ELF/Arch/SPARCV9.cpp
    lld/ELF/Driver.cpp
    lld/ELF/InputSection.cpp
    lld/ELF/ScriptParser.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp
index 709db1c07a31..a8dc48bbd4f1 100644
--- a/lld/ELF/Arch/SPARCV9.cpp
+++ b/lld/ELF/Arch/SPARCV9.cpp
@@ -55,6 +55,14 @@ RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
   case R_SPARC_UA32:
   case R_SPARC_64:
   case R_SPARC_UA64:
+  case R_SPARC_H44:
+  case R_SPARC_M44:
+  case R_SPARC_L44:
+  case R_SPARC_HH22:
+  case R_SPARC_HM10:
+  case R_SPARC_LM22:
+  case R_SPARC_HI22:
+  case R_SPARC_LO10:
     return R_ABS;
   case R_SPARC_PC10:
   case R_SPARC_PC22:
@@ -69,6 +77,9 @@ RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
     return R_PLT_PC;
   case R_SPARC_NONE:
     return R_NONE;
+  case R_SPARC_TLS_LE_HIX22:
+  case R_SPARC_TLS_LE_LOX10:
+    return R_TLS;
   default:
     error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
           ") against symbol " + toString(s));
@@ -103,9 +114,15 @@ void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
     break;
   case R_SPARC_GOT22:
   case R_SPARC_PC22:
+  case R_SPARC_LM22:
     // T-imm22
     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
     break;
+  case R_SPARC_HI22:
+    // V-imm22
+    checkUInt(loc, val >> 10, 22, rel);
+    write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
+    break;
   case R_SPARC_WDISP19:
     // V-disp19
     checkInt(loc, val, 21, rel);
@@ -116,11 +133,45 @@ void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
     // T-simm10
     write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));
     break;
+  case R_SPARC_LO10:
+    // T-simm13
+    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff));
+    break;
   case R_SPARC_64:
   case R_SPARC_UA64:
     // V-xword64
     write64be(loc, val);
     break;
+  case R_SPARC_HH22:
+    // V-imm22
+    checkUInt(loc, val >> 42, 22, rel);
+    write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff));
+    break;
+  case R_SPARC_HM10:
+    // T-simm13
+    write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff));
+    break;
+  case R_SPARC_H44:
+    // V-imm22
+    checkUInt(loc, val >> 22, 22, rel);
+    write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff));
+    break;
+  case R_SPARC_M44:
+    // T-imm10
+    write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff));
+    break;
+  case R_SPARC_L44:
+    // T-imm13
+    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff));
+    break;
+  case R_SPARC_TLS_LE_HIX22:
+    // T-imm22
+    write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
+    break;
+  case R_SPARC_TLS_LE_LOX10:
+    // T-simm13
+    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);
+    break;
   default:
     llvm_unreachable("unknown relocation");
   }

diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index d223ed47b461..35153a1bff8b 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -149,6 +149,7 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef emul) {
           .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64})
           .Case("elf_i386", {ELF32LEKind, EM_386})
           .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
+          .Case("elf64_sparc", {ELF64BEKind, EM_SPARCV9})
           .Default({ELFNoneKind, EM_NONE});
 
   if (ret.first == ELFNoneKind)

diff  --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 13c3dd486c33..e150cb8f118d 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -650,6 +650,7 @@ static int64_t getTlsTpOffset(const Symbol &s) {
 
     // Variant 2.
   case EM_HEXAGON:
+  case EM_SPARCV9:
   case EM_386:
   case EM_X86_64:
     return s.getVA(0) - tls->p_memsz -

diff  --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 037cb9f31eff..b487f31f9cae 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -404,6 +404,7 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
       .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS})
       .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV})
       .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV})
+      .Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9})
       .Default({ELFNoneKind, EM_NONE});
 }
 

diff  --git a/lld/test/ELF/emulation-sparc.s b/lld/test/ELF/emulation-sparc.s
new file mode 100644
index 000000000000..8b89a462ed8a
--- /dev/null
+++ b/lld/test/ELF/emulation-sparc.s
@@ -0,0 +1,26 @@
+# REQUIRES: sparc
+# RUN: llvm-mc -filetype=obj -triple=sparcv9 %s -o %t.o
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-readobj --file-headers %t1 | FileCheck --check-prefix=V9 %s
+# RUN: ld.lld -m elf64_sparc %t.o -o %t2
+# RUN: cmp %t1 %t2
+# RUN: echo 'OUTPUT_FORMAT(elf64-sparc)' > %t.lds
+# RUN: ld.lld -T %t.lds %t.o -o %t3
+# RUN: llvm-readobj --file-headers %t3 | FileCheck --check-prefix=V9 %s
+
+# V9:      ElfHeader {
+# V9-NEXT:   Ident {
+# V9-NEXT:     Magic: (7F 45 4C 46)
+# V9-NEXT:     Class: 64-bit (0x2)
+# V9-NEXT:     DataEncoding: BigEndian (0x2)
+# V9-NEXT:     FileVersion: 1
+# V9-NEXT:     OS/ABI: SystemV (0x0)
+# V9-NEXT:     ABIVersion: 0
+# V9-NEXT:     Unused: (00 00 00 00 00 00 00)
+# V9-NEXT:   }
+# V9-NEXT:   Type: Executable (0x2)
+# V9-NEXT:   Machine: EM_SPARCV9 (0x2B)
+# V9-NEXT:   Version: 1
+
+.globl _start
+_start:

diff  --git a/lld/test/ELF/sparcv9-reloc.s b/lld/test/ELF/sparcv9-reloc.s
new file mode 100644
index 000000000000..ec9abd6dc3bb
--- /dev/null
+++ b/lld/test/ELF/sparcv9-reloc.s
@@ -0,0 +1,39 @@
+# REQUIRES: sparc
+# RUN: llvm-mc -filetype=obj -triple=sparcv9 %s -o %t.o
+# RUN: ld.lld %t.o --defsym=a=0x0123456789ABCDEF --defsym=b=0x0123456789A --defsym=c=0x01234567 -o %t
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+# RUN: llvm-objdump -s %t | FileCheck --check-prefix=HEX %s
+
+## R_SPARC_HH22, R_SPARC_HM10
+# CHECK-LABEL: section .ABS_64:
+# CHECK:        sethi 18641, %o0
+# CHECK-NEXT:   or %o0, 359, %o0
+.section .ABS_64,"ax", at progbits
+  sethi %hh(a), %o0
+  or    %o0, %hm(a), %o0
+
+## R_SPARC_H44, R_SPARC_M44, R_SPARC_L44
+# CHECK-LABEL: section .ABS_44:
+# CHECK:        sethi 18641, %o0
+# CHECK:        or %o0, 359, %o0
+# CHECK:        or %o0, 2202, %o0
+.section .ABS_44,"ax", at progbits
+  sethi %h44(b), %o0
+  or    %o0, %m44(b), %o0
+  sllx  %o0, 12, %o0
+  or    %o0, %l44(b), %o0
+
+## R_SPARC_HI22, R_SPARC_LO10
+# CHECK-LABEL: section .ABS_32:
+# CHECK:        sethi 18641, %o0
+# CHECK-NEXT:   or %o0, 359, %o0
+.section .ABS_32,"ax", at progbits
+  sethi %hi(c), %o0
+  or    %o0, %lo(c), %o0
+
+## R_SPARC_64, R_SPARC_32
+# HEX-LABEL: section .ABS_DATA:
+# HEX-NEXT:  01234567 89abcdef 01234567
+.section .ABS_DATA,"ax", at progbits
+  .quad a
+  .long c

diff  --git a/lld/test/ELF/sparcv9-tls-le.s b/lld/test/ELF/sparcv9-tls-le.s
new file mode 100644
index 000000000000..2d4fec9ccc8d
--- /dev/null
+++ b/lld/test/ELF/sparcv9-tls-le.s
@@ -0,0 +1,17 @@
+# REQUIRES: sparc
+# RUN: llvm-mc -filetype=obj -triple=sparcv9 %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
+
+## %hix(@tpoff(a)) = ~(st_value(a) - 1026) >> 10 = 1
+## %lo(@tpoff(a)) = (st_value(a) - 1026) & 0x3ff | 0x1c00 = -2 (0x1ffe)
+# LE:      sethi 1, %o0
+# LE-NEXT: xor %o0, -2, %o0
+sethi %tle_hix22(a), %o0
+xor   %o0, %tle_lox10(a), %o0
+
+.section .tbss
+  .globl a
+a:
+  .zero 1024+2
+b:


        


More information about the llvm-commits mailing list