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,
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:
+ internalLinkerError(getErrorLocation(buf),
+ "cannot read addend for relocation " + toString(type));
+ return 0;
+ }
+}
+
void AArch64::writeGotPlt(uint8_t *buf, const Symbol &) const {
write64(buf, in.plt->getVA());
}
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");
}
config->shared) {
if (in.got->addDynTlsEntry(sym)) {
uint64_t off = in.got->getGlobalDynOffset(sym);
- mainPart->relaDyn->addReloc({target->tlsDescRel, in.got, off,
- sym.isPreemptible
- ? DynamicReloc::AgainstSymbol
- : DynamicReloc::AddendOnlyWithTargetVA,
- sym, 0, R_ABS});
+ mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
+ target->tlsDescRel, in.got, off, sym, target->tlsDescRel);
}
if (expr != R_TLSDESC_CALL)
c.relocations.push_back({expr, type, offset, addend, &sym});
addRelativeReloc(in.got, off, sym, 0, R_ABS, target->symbolicRel);
return;
}
- mainPart->relaDyn->addReloc(
- sym.isPreemptible ? DynamicReloc::AgainstSymbol
- : DynamicReloc::AddendOnlyWithTargetVA,
- sym.isTls() ? target->tlsGotRel : target->gotRel, in.got, off, sym, 0,
- sym.isPreemptible ? R_ADDEND : R_ABS, target->symbolicRel);
+ mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
+ sym.isTls() ? target->tlsGotRel : target->gotRel, in.got, off, sym,
+ target->symbolicRel);
}
// Return true if we can define a symbol in the executable that
sym, addend, expr, addendRelType);
}
+void RelocationBaseSection::addAddendOnlyRelocIfNonPreemptible(
+ RelType dynType, InputSectionBase *isec, uint64_t offsetInSec, Symbol &sym,
+ RelType addendRelType) {
+ // No need to write an addend to the section for preemptible symbols.
+ if (sym.isPreemptible)
+ addReloc({dynType, isec, offsetInSec, DynamicReloc::AgainstSymbol, sym, 0,
+ R_ABS});
+ else
+ addReloc(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec, offsetInSec,
+ sym, 0, R_ABS, addendRelType);
+}
+
void RelocationBaseSection::addReloc(DynamicReloc::Kind kind, RelType dynType,
InputSectionBase *inputSec,
uint64_t offsetInSec, Symbol &sym,
void addRelativeReloc(RelType dynType, InputSectionBase *isec,
uint64_t offsetInSec, Symbol &sym, int64_t addend,
RelType addendRelType, RelExpr expr);
+ /// Add a dynamic relocation using the target address of \p sym as the addend
+ /// if \p sym is non-preemptible. Otherwise add a relocation against \p sym.
+ void addAddendOnlyRelocIfNonPreemptible(RelType dynType,
+ InputSectionBase *isec,
+ uint64_t offsetInSec, Symbol &sym,
+ RelType addendRelType);
void addReloc(DynamicReloc::Kind kind, RelType dynType,
InputSectionBase *inputSec, uint64_t offsetInSec, Symbol &sym,
int64_t addend, RelExpr expr, RelType addendRelType);
--- /dev/null
+/// 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 %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-prefixes=RELA,RELA-NO-ADDENDS
+// 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-prefixes=RELA,RELA-WITH-ADDENDS
+
+// 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-NO-ADDENDS-NEXT: 0x00020350 00000000 00000000 00000000 00000000
+// RELA-WITH-ADDENDS-NEXT: 0x00020350 00000000 00000000 04000000 00000000
+/// Addend 0x4 for R_AARCH64_TLSDESC -----^
+// RELA-EMPTY:
+
+// 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 -----^
+// REL-EMPTY:
+
+ .text
+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
+
+ .section .tbss,"awT",@nobits
+ .p2align 2
+ .hidden x
+x:
+ .word 0
+
+ .p2align 2
+ .hidden y
+y:
+ .word 0