From: LemonBoy Date: Fri, 17 Apr 2020 14:58:15 +0000 (-0700) Subject: [ELF] Support a few more SPARCv9 relocations X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=aff950e95d4a0b09fa8629e7358e5e06ea2ceb87;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp index 709db1c..a8dc48b 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 d223ed4..35153a1 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -149,6 +149,7 @@ static std::tuple 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 13c3dd4..e150cb8 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 037cb9f..b487f31 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -404,6 +404,7 @@ static std::pair 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 0000000..8b89a46 --- /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 0000000..ec9abd6d --- /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",@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",@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",@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",@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 0000000..2d4fec9 --- /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: