diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index bd1d78964f20c..d29932dd42a2e 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -125,6 +125,13 @@ RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s, case R_HEX_GOT_16_X: case R_HEX_GOT_32_6_X: return R_GOTPLT; + case R_HEX_TPREL_11_X: + case R_HEX_TPREL_16: + case R_HEX_TPREL_16_X: + case R_HEX_TPREL_32_6_X: + case R_HEX_TPREL_HI16: + case R_HEX_TPREL_LO16: + return R_TLS; default: error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + ") against symbol " + toString(s)); @@ -222,6 +229,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_HEX_11_X: case R_HEX_GOT_11_X: case R_HEX_GOTREL_11_X: + case R_HEX_TPREL_11_X: or32le(loc, applyMask(findMaskR11(read32le(loc)), val & 0x3f)); break; case R_HEX_12_X: @@ -230,8 +238,12 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_HEX_16_X: // These relocs only have 6 effective bits. case R_HEX_GOT_16_X: case R_HEX_GOTREL_16_X: + case R_HEX_TPREL_16_X: or32le(loc, applyMask(findMaskR16(read32le(loc)), val & 0x3f)); break; + case R_HEX_TPREL_16: + or32le(loc, applyMask(findMaskR16(read32le(loc)), val & 0xffff)); + break; case R_HEX_32: case R_HEX_32_PCREL: or32le(loc, val); @@ -239,6 +251,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_HEX_32_6_X: case R_HEX_GOT_32_6_X: case R_HEX_GOTREL_32_6_X: + case R_HEX_TPREL_32_6_X: or32le(loc, applyMask(0x0fff3fff, val >> 6)); break; case R_HEX_B9_PCREL: @@ -272,10 +285,12 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; case R_HEX_GOTREL_HI16: case R_HEX_HI16: + case R_HEX_TPREL_HI16: or32le(loc, applyMask(0x00c03fff, val >> 16)); break; case R_HEX_GOTREL_LO16: case R_HEX_LO16: + case R_HEX_TPREL_LO16: or32le(loc, applyMask(0x00c03fff, val)); break; default: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 7dceddb5659dd..25375ea2a5748 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -636,6 +636,7 @@ static int64_t getTlsTpOffset(const Symbol &s) { return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1)); // Variant 2. + case EM_HEXAGON: case EM_386: case EM_X86_64: return s.getVA(0) - tls->p_memsz - diff --git a/lld/test/ELF/hexagon-tls-le.s b/lld/test/ELF/hexagon-tls-le.s new file mode 100644 index 0000000000000..eadfb4ddd5354 --- /dev/null +++ b/lld/test/ELF/hexagon-tls-le.s @@ -0,0 +1,56 @@ +# REQUIRES: hexagon +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d --print-imm-hex %t | FileCheck %s + + .globl _start + .type _start, @function +_start: +r0 = ugp + +# R_HEX_TPREL_32_6_X and R_HEX_TPREL_16_X +# CHECK: { immext(#0xffffffc0) +# CHECK-NEXT: r1 = add(r0,##-0x10) } + r1 = add(r0,##a@TPREL) + +# R_HEX_TPREL_32_6_X and R_HEX_TPREL_11_X +# CHECK: { immext(#0xffffffc0) +# CHECK-NEXT: r2 = memw(r0+##-0x10) } + r2 = memw(r0+##a@TPREL) + +# R_HEX_TPREL_HI16 +# CHECK: { r3.h = #0xffff } + r3.h = #a@TPREL + +# R_HEX_TPREL_LO16 +# CHECK: { r3.l = #0xfff0 } + r3.l = #a@TPREL + +# R_HEX_TPREL_16 +# CHECK: { r4 = #-0x10 } + r4 = #a@TPREL + + .section .tdata,"awT",@progbits + .globl a + .p2align 2 +a: + .word 1 + .size a, 4 + + .globl b + .p2align 2 +b: + .word 2 + .size b, 4 + + .globl c + .p2align 2 +c: + .word 3 + .size c, 4 + + .globl d + .p2align 2 +d: + .word 4 + .size d, 4