mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 08:30:34 +08:00
[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
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 -
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
|
||||
26
lld/test/ELF/emulation-sparc.s
Normal file
26
lld/test/ELF/emulation-sparc.s
Normal file
@@ -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:
|
||||
39
lld/test/ELF/sparcv9-reloc.s
Normal file
39
lld/test/ELF/sparcv9-reloc.s
Normal file
@@ -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
|
||||
17
lld/test/ELF/sparcv9-tls-le.s
Normal file
17
lld/test/ELF/sparcv9-tls-le.s
Normal file
@@ -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:
|
||||
Reference in New Issue
Block a user