Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV] Support RISC-V TLSDESC in LLD #77516

Conversation

ilovepi
Copy link
Contributor

@ilovepi ilovepi commented Jan 9, 2024

This patch adds support for RISC-V TLSDESC relocations, as described in
riscv-non-isa/riscv-elf-psabi-doc#373.

It does not attempt to handle relaxation for these cases, which will be
handled separately.

Created using spr 1.3.4
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 9, 2024

@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-elf

Author: Paul Kirth (ilovepi)

Changes

This patch adds support for RISC-V TLSDESC relocations, as described in
riscv-non-isa/riscv-elf-psabi-doc#373.

It does not attempt to handle relaxation for these cases, which will be
handled separately.


Full diff: https://github.com/llvm/llvm-project/pull/77516.diff

6 Files Affected:

  • (modified) lld/ELF/Arch/RISCV.cpp (+20)
  • (modified) lld/ELF/InputSection.cpp (+1)
  • (modified) lld/ELF/Relocations.cpp (+2-2)
  • (modified) lld/ELF/Relocations.h (+4)
  • (modified) lld/ELF/Writer.cpp (+2-1)
  • (added) lld/test/ELF/riscv-tlsdesc-le.s (+43)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 1d3d179e5d6fb5..460cccbabdb002 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -44,6 +44,7 @@ class RISCV final : public TargetInfo {
   void relocate(uint8_t *loc, const Relocation &rel,
                 uint64_t val) const override;
   void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
+  RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
   bool relaxOnce(int pass) const override;
 };
 
@@ -120,6 +121,8 @@ RISCV::RISCV() {
   }
   gotRel = symbolicRel;
 
+  tlsDescRel = R_RISCV_TLSDESC_CALL;
+
   // .got[0] = _DYNAMIC
   gotHeaderEntriesNum = 1;
 
@@ -298,6 +301,13 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
     return R_TLSGD_PC;
   case R_RISCV_TLS_GOT_HI20:
     return R_GOT_PC;
+  case R_RISCV_TLSDESC_HI20:
+    return R_TLSDESC_PC;
+  case R_RISCV_TLSDESC_LOAD_LO12:
+  case R_RISCV_TLSDESC_ADD_LO12:
+    return R_TLSDESC;
+  case R_RISCV_TLSDESC_CALL:
+    return R_TLSDESC_CALL;
   case R_RISCV_TPREL_HI20:
   case R_RISCV_TPREL_LO12_I:
   case R_RISCV_TPREL_LO12_S:
@@ -420,6 +430,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_RISCV_PCREL_HI20:
   case R_RISCV_TLS_GD_HI20:
   case R_RISCV_TLS_GOT_HI20:
+  case R_RISCV_TLSDESC_HI20:
   case R_RISCV_TPREL_HI20:
   case R_RISCV_HI20: {
     uint64_t hi = val + 0x800;
@@ -430,6 +441,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
 
   case R_RISCV_PCREL_LO12_I:
   case R_RISCV_TPREL_LO12_I:
+  case R_RISCV_TLSDESC_LOAD_LO12:
+  case R_RISCV_TLSDESC_ADD_LO12:
   case R_RISCV_LO12_I: {
     uint64_t hi = (val + 0x800) >> 12;
     uint64_t lo = val - (hi << 12);
@@ -557,6 +570,13 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
   }
 }
 
+RelExpr RISCV::adjustTlsExpr(RelType type, RelExpr expr) const {
+  if (expr == R_RELAX_TLS_GD_TO_IE) {
+    return R_RELAX_TLS_GD_TO_IE_ABS;
+  }
+  return expr;
+}
+
 namespace {
 struct SymbolAnchor {
   uint64_t offset;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 53b496bd084258..90f55c4b8a6b1c 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -851,6 +851,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
     return sym.getSize() + a;
   case R_TLSDESC:
     return in.got->getTlsDescAddr(sym) + a;
+  case R_RISCV_TLSDESC_HI:
   case R_TLSDESC_PC:
     return in.got->getTlsDescAddr(sym) + a - p;
   case R_TLSDESC_GOTPLT:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 20eb02b8798447..6e67a13731fea8 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1269,7 +1269,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
     return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
 
   if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
-            R_TLSDESC_GOTPLT>(expr) &&
+            R_TLSDESC_GOTPLT, R_RISCV_TLSDESC_HI>(expr) &&
       config->shared) {
     if (expr != R_TLSDESC_CALL) {
       sym.setFlags(NEEDS_TLSDESC);
@@ -1333,7 +1333,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
 
   if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
             R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC,
-            R_LOONGARCH_TLSGD_PAGE_PC>(expr)) {
+            R_LOONGARCH_TLSGD_PAGE_PC, R_RISCV_TLSDESC_HI>(expr)) {
     if (!toExecRelax) {
       sym.setFlags(NEEDS_TLSGD);
       c.addReloc({expr, type, offset, addend, &sym});
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index cfb9092149f3e0..9a24fe8a219dab 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -103,6 +103,10 @@ enum RelExpr {
   R_RISCV_ADD,
   R_RISCV_LEB128,
   R_RISCV_PC_INDIRECT,
+  R_RISCV_TLSDESC_HI,
+  R_RISCV_TLSDESC_LOAD_LO,
+  R_RISCV_TLSDESC_ADD_LO,
+  R_RISCV_TLSDESC_CALLER,
   // Same as R_PC but with page-aligned semantics.
   R_LOONGARCH_PAGE_PC,
   // Same as R_PLT_PC but with page-aligned semantics.
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index dfec5e07301a74..34bb3da2a1c343 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1950,7 +1950,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
       }
     }
 
-    if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
+    if (config->emachine == EM_386 || config->emachine == EM_X86_64 ||
+        config->emachine == EM_RISCV) {
       // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
       // way that:
       //
diff --git a/lld/test/ELF/riscv-tlsdesc-le.s b/lld/test/ELF/riscv-tlsdesc-le.s
new file mode 100644
index 00000000000000..6aa670cffb59b8
--- /dev/null
+++ b/lld/test/ELF/riscv-tlsdesc-le.s
@@ -0,0 +1,43 @@
+// RUN: llvm-mc -filetype=obj -triple=riscv64-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t.so | FileCheck %s
+// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=REL %s
+
+//      CHECK: 00000000000012d8 <_start>:
+// CHECK-NEXT:    12d8:       auipc   a0, 1
+// CHECK-NEXT:    12dc:       ld      a1, 920(a0)
+// CHECK-NEXT:    12e0:       addi    a0, a0, 920
+// CHECK-NEXT:    12e4:       jalr    t0, a1
+// CHECK-NEXT:    12e8:       add     a0, a0, tp
+// CHECK-NEXT:    12ec:       ret
+
+//      REL: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 2 entries
+//      REL: R_RISCV_TLSDESC_CALL ffffffffffffffe8
+// REL-NEXT: R_RISCV_TLSDESC_CALL 0
+
+	.text
+	.attribute	4, 16
+	.attribute	5, "rv64i2p1"
+	.file	"<stdin>"
+	.globl	_start                              # -- Begin function _start
+	.p2align	2
+	.type	_start,@function
+_start:                                     # @_start
+# %bb.0:                                # %entry
+.Ltlsdesc_hi0:
+	auipc	a0, %tlsdesc_hi(unspecified)
+	ld	a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
+	addi	a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+	jalr	t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
+	add	a0, a0, tp
+	ret
+.Lfunc_end0:
+	.size	_start, .Lfunc_end0-_start
+                                        # -- End function
+	.section	".note.GNU-stack","",@progbits
+
+        .section .tbss,"awT",@nobits
+        .p2align 2
+
+unspecified:
+        .zero    4

@MaskRay
Copy link
Member

MaskRay commented Jan 22, 2024

The patch does not need address TLSDESC to TLS LE and IE optimizations, which is pretty important. I think we don't need linker relaxation, but we do need TLS optimization for correctness. The changes are pretty subtle, I'll probably create patch based on this with you as a co-author.

@MaskRay
Copy link
Member

MaskRay commented Jan 23, 2024

I have found several issues.

#79099 reuses an old revision of the LLVM part but otherwise is a rewrite and should fix these issues as well as implement linker relaxation.

@ilovepi
Copy link
Contributor Author

ilovepi commented Jan 26, 2024

Abandon in favor of #79239

@ilovepi ilovepi closed this Jan 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants