diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -34,6 +34,7 @@ RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; RelType getDynRel(RelType type) const override; + int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; void writeGotPlt(uint8_t *buf, const Symbol &s) const override; void writePltHeader(uint8_t *buf) const override; void writePlt(uint8_t *buf, const Symbol &sym, @@ -194,6 +195,16 @@ return R_AARCH64_NONE; } +int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const { + switch (type) { + case R_AARCH64_TLSDESC: + return read64(buf + 8); + default: + errorOrWarn(toString(type) + " not handled in getImplicitAddend"); + return 0; + } +} + void AArch64::writeGotPlt(uint8_t *buf, const Symbol &) const { write64(buf, in.plt->getVA()); } @@ -467,6 +478,10 @@ case R_AARCH64_TLSDESC_ADD_LO12: or32AArch64Imm(loc, val); break; + case R_AARCH64_TLSDESC: + // For R_AARCH64_TLSDESC the addend is stored in the second 64-bit word. + write64(loc + 8, val); + break; default: llvm_unreachable("unknown relocation"); } diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -200,8 +200,8 @@ config->shared) { if (in.got->addDynTlsEntry(sym)) { uint64_t off = in.got->getGlobalDynOffset(sym); - mainPart->relaDyn->addReloc({target->tlsDescRel, in.got, off, - !sym.isPreemptible, &sym, 0, R_ABS}); + mainPart->relaDyn->addReloc(target->tlsDescRel, in.got, off, &sym, 0, + R_ABS, target->tlsDescRel); } if (expr != R_TLSDESC_CALL) c.relocations.push_back({expr, type, offset, addend, &sym}); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1613,7 +1613,8 @@ // it if the written value would be zero. if (config->writeAddends && (expr != R_ADDEND || addend != 0)) inputSec->relocations.push_back({expr, type, offsetInSec, addend, sym}); - addReloc({dynType, inputSec, offsetInSec, expr != R_ADDEND, sym, addend, expr}); + addReloc({dynType, inputSec, offsetInSec, expr != R_ADDEND, sym, addend, expr, + (bool)sym->isPreemptible}); } void RelocationBaseSection::addReloc(const DynamicReloc &reloc) { diff --git a/lld/test/ELF/aarch64-tlsdesc-zrel.s b/lld/test/ELF/aarch64-tlsdesc-zrel.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/aarch64-tlsdesc-zrel.s @@ -0,0 +1,75 @@ +/// Check that we write addends for AArch64 TLSDESC relocations with -z rel +/// See https://bugs.llvm.org/show_bug.cgi?id=47009 +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t-rela.so +// RUN: llvm-readobj -W -r -x .got %t-rela.so | FileCheck %s --check-prefix=RELA +// RELA: Relocations [ +// RELA-NEXT: Section (5) .rela.dyn { +// RELA-NEXT: 0x20340 R_AARCH64_TLSDESC - 0x0 +// RELA-NEXT: 0x20350 R_AARCH64_TLSDESC - 0x4 +// RELA-NEXT: } +// RELA-NEXT: ] +// RELA-NEXT: Hex dump of section '.got': +// RELA-NEXT: 0x00020340 00000000 00000000 00000000 00000000 +// RELA-NEXT: 0x00020350 00000000 00000000 00000000 00000000 + +// RUN: ld.lld -shared %t.o -o %t-rela-addends.so --apply-dynamic-relocs +// RUN: llvm-readobj -W -r -x .got %t-rela-addends.so | FileCheck %s --check-prefix=RELA-WITH-ADDENDS +// RELA-WITH-ADDENDS: Relocations [ +// RELA-WITH-ADDENDS-NEXT: Section (5) .rela.dyn { +// RELA-WITH-ADDENDS-NEXT: 0x20340 R_AARCH64_TLSDESC - 0x0 +// RELA-WITH-ADDENDS-NEXT: 0x20350 R_AARCH64_TLSDESC - 0x4 +// RELA-WITH-ADDENDS-NEXT: } +// RELA-WITH-ADDENDS-NEXT: ] +// RELA-WITH-ADDENDS-NEXT: Hex dump of section '.got': +// RELA-WITH-ADDENDS-NEXT: 0x00020340 00000000 00000000 00000000 00000000 +// RELA-WITH-ADDENDS-NEXT: 0x00020350 00000000 00000000 04000000 00000000 +/// Addend 0x4 for R_AARCH64_TLSDESC -----^ + +// RUN: ld.lld -shared %t.o -o %t-rel.so -z rel +// RUN: llvm-readobj -W -r -x .got %t-rel.so | FileCheck %s --check-prefix=REL +// REL: Relocations [ +// REL-NEXT: Section (5) .rel.dyn { +// REL-NEXT: 0x20330 R_AARCH64_TLSDESC -{{$}} +// REL-NEXT: 0x20340 R_AARCH64_TLSDESC -{{$}} +// REL-NEXT: } +// REL-NEXT: ] +// REL-NEXT: Hex dump of section '.got': +// REL-NEXT: 0x00020330 00000000 00000000 00000000 00000000 +// REL-NEXT: 0x00020340 00000000 00000000 04000000 00000000 +/// Addend 0x4 for R_AARCH64_TLSDESC -----^ + + .text + .type foo,@function +foo: // @foo + adrp x0, :tlsdesc:x + ldr x1, [x0, :tlsdesc_lo12:x] + add x0, x0, :tlsdesc_lo12:x + .tlsdesccall x + blr x1 + adrp x0, :tlsdesc:y + ldr x1, [x0, :tlsdesc_lo12:y] + add x0, x0, :tlsdesc_lo12:y + .tlsdesccall y + blr x1 + ret +.Lfunc_end0: + .size foo, .Lfunc_end0-foo + + .hidden x // @x + .type x,@object + .section .tbss,"awT",@nobits + .globl x + .p2align 2 +x: + .word 0 + .size x, 4 + + .hidden y // @y + .type y,@object + .globl y + .p2align 2 +y: + .word 0 // 0x0 + .size y, 4