[lld] Enough LLD changes to bootstrap OpenBSD on sparc64 (PR #207609)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 5 12:52:16 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld

Author: Kirill A. Korinsky (catap)

<details>
<summary>Changes</summary>

This PR consumes https://github.com/llvm/llvm-project/pull/137919, adds my bits from https://github.com/catap/OpenBSD-src/tree/sparc64 which I had used to actually build OpenBSD by using LLVM toolchain.

It also contains a bit of tests.

I do not tried to build OpenBSD by exactly this branch, but it looks close enough and I had resolved only one conflicts which was introduced by 3be67c72f5d5b9f459c0b11fce2c92c2cac5a984

---

Patch is 31.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/207609.diff


18 Files Affected:

- (modified) lld/ELF/Arch/SPARCV9.cpp (+262-34) 
- (modified) lld/ELF/Driver.cpp (+4-3) 
- (modified) lld/ELF/InputSection.cpp (+1) 
- (modified) lld/ELF/Relocations.cpp (+20-13) 
- (modified) lld/ELF/Relocations.h (+1) 
- (modified) lld/ELF/Symbols.cpp (+6) 
- (modified) lld/ELF/Symbols.h (+1) 
- (modified) lld/ELF/SyntheticSections.cpp (+27-6) 
- (modified) lld/ELF/Target.cpp (+6) 
- (modified) lld/ELF/Target.h (+6-1) 
- (modified) lld/ELF/Writer.cpp (+7-3) 
- (added) lld/test/ELF/sparcv9-got-header.s (+11) 
- (added) lld/test/ELF/sparcv9-gotdata-relax.s (+37) 
- (added) lld/test/ELF/sparcv9-plt.s (+23) 
- (added) lld/test/ELF/sparcv9-rela.s (+14) 
- (added) lld/test/ELF/sparcv9-reloc-additional.s (+43) 
- (added) lld/test/ELF/sparcv9-tls-dynamic.s (+38) 
- (added) lld/test/ELF/sparcv9-ua64-dynrel.s (+29) 


``````````diff
diff --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp
index 405be69a8f572..1847fb295ab41 100644
--- a/lld/ELF/Arch/SPARCV9.cpp
+++ b/lld/ELF/Arch/SPARCV9.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "InputFiles.h"
 #include "RelocScan.h"
+#include "SymbolTable.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
@@ -25,6 +27,8 @@ class SPARCV9 final : public TargetInfo {
   SPARCV9(Ctx &);
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
+  RelType getDynRel(RelType type) const override;
+  void writeGotHeader(uint8_t *buf) const override;
   void writePlt(uint8_t *buf, const Symbol &sym,
                 uint64_t pltEntryAddr) const override;
   template <class ELFT, class RelTy>
@@ -34,6 +38,12 @@ class SPARCV9 final : public TargetInfo {
   }
   void relocate(uint8_t *loc, const Relocation &rel,
                 uint64_t val) const override;
+  void finalizeRelocScan() override;
+  RelExpr adjustGotOffExpr(RelType type, const Symbol &sym, int64_t addend,
+                           const uint8_t *loc) const override;
+
+private:
+  void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const;
 };
 } // namespace
 
@@ -42,9 +52,15 @@ SPARCV9::SPARCV9(Ctx &ctx) : TargetInfo(ctx) {
   gotRel = R_SPARC_GLOB_DAT;
   pltRel = R_SPARC_JMP_SLOT;
   relativeRel = R_SPARC_RELATIVE;
+  iRelativeRel = R_SPARC_IRELATIVE;
   symbolicRel = R_SPARC_64;
+  tlsGotRel = R_SPARC_TLS_TPOFF64;
+  tlsModuleIndexRel = R_SPARC_TLS_DTPMOD64;
+  tlsOffsetRel = R_SPARC_TLS_DTPOFF64;
+  gotHeaderEntriesNum = 1;
   pltEntrySize = 32;
   pltHeaderSize = 4 * pltEntrySize;
+  usesGotPlt = false;
 
   defaultCommonPageSize = 8192;
   defaultMaxPageSize = 0x100000;
@@ -72,6 +88,12 @@ RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
   }
 }
 
+RelType SPARCV9::getDynRel(RelType type) const {
+  if (type == symbolicRel || type == R_SPARC_UA64)
+    return type;
+  return R_SPARC_NONE;
+}
+
 template <class ELFT, class RelTy>
 void SPARCV9::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
   RelocScan rs(ctx, &sec);
@@ -89,21 +111,33 @@ void SPARCV9::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
     RelExpr expr;
     switch (type) {
     case R_SPARC_NONE:
+    case R_SPARC_TLS_GD_ADD:
+    case R_SPARC_TLS_LDM_ADD:
+    case R_SPARC_TLS_LDO_ADD:
+    case R_SPARC_TLS_IE_LD:
+    case R_SPARC_TLS_IE_LDX:
+    case R_SPARC_TLS_IE_ADD:
       continue;
 
     // Absolute relocations:
+    case R_SPARC_8:
+    case R_SPARC_16:
     case R_SPARC_32:
+    case R_SPARC_HI22:
+    case R_SPARC_13:
+    case R_SPARC_LO10:
     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:
+    case R_SPARC_HIX22:
+    case R_SPARC_LOX10:
+    case R_SPARC_H44:
+    case R_SPARC_M44:
+    case R_SPARC_L44:
+    case R_SPARC_UA64:
+    case R_SPARC_UA16:
       expr = R_ABS;
       break;
 
@@ -111,20 +145,38 @@ void SPARCV9::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
     case R_SPARC_WPLT30:
       rs.processR_PLT_PC(type, offset, addend, sym);
       continue;
+    case R_SPARC_TLS_GD_CALL:
+    case R_SPARC_TLS_LDM_CALL:
+      sec.addReloc({R_PLT_PC, type, offset, addend, &sym});
+      continue;
 
     // PC-relative relocations:
-    case R_SPARC_PC10:
-    case R_SPARC_PC22:
+    case R_SPARC_DISP8:
+    case R_SPARC_DISP16:
     case R_SPARC_DISP32:
     case R_SPARC_WDISP30:
+    case R_SPARC_WDISP22:
+    case R_SPARC_PC10:
+    case R_SPARC_PC22:
+    case R_SPARC_WDISP16:
+    case R_SPARC_WDISP19:
+    case R_SPARC_DISP64:
       rs.processR_PC(type, offset, addend, sym);
       continue;
 
     // GOT relocations:
     case R_SPARC_GOT10:
+    case R_SPARC_GOT13:
     case R_SPARC_GOT22:
+    case R_SPARC_GOTDATA_OP_HIX22:
+    case R_SPARC_GOTDATA_OP_LOX10:
+    case R_SPARC_GOTDATA_OP:
       expr = R_GOT_OFF;
       break;
+    case R_SPARC_GOTDATA_HIX22:
+    case R_SPARC_GOTDATA_LOX10:
+      expr = R_GOTREL;
+      break;
 
     // TLS LE relocations:
     case R_SPARC_TLS_LE_HIX22:
@@ -133,6 +185,25 @@ void SPARCV9::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
         continue;
       expr = R_TPREL;
       break;
+    case R_SPARC_TLS_GD_HI22:
+    case R_SPARC_TLS_GD_LO10:
+      sym.setFlags(NEEDS_TLSGD);
+      sec.addReloc({R_TLSGD_GOT, type, offset, addend, &sym});
+      continue;
+    case R_SPARC_TLS_LDM_HI22:
+    case R_SPARC_TLS_LDM_LO10:
+      ctx.needsTlsLd.store(true, std::memory_order_relaxed);
+      sec.addReloc({R_TLSLD_GOT, type, offset, addend, &sym});
+      continue;
+    case R_SPARC_TLS_LDO_HIX22:
+    case R_SPARC_TLS_LDO_LOX10:
+      expr = R_DTPREL;
+      break;
+    case R_SPARC_TLS_IE_HI22:
+    case R_SPARC_TLS_IE_LO10:
+      sym.setFlags(NEEDS_TLSIE);
+      sec.addReloc({R_GOT, type, offset, addend, &sym});
+      continue;
 
     default:
       Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset)
@@ -146,71 +217,139 @@ void SPARCV9::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
 
 void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
                        uint64_t val) const {
+  switch (rel.expr) {
+  case R_RELAX_GOT_OFF:
+    return relaxGot(loc, rel, val);
+  default:
+    break;
+  }
+
   switch (rel.type) {
+  case R_SPARC_8:
+    // V-byte8
+    checkUInt(ctx, loc, val, 8, rel);
+    *loc = val;
+    break;
+  case R_SPARC_16:
+  case R_SPARC_UA16:
+    // V-half16
+    checkUInt(ctx, loc, val, 16, rel);
+    write16be(loc, val);
+    break;
   case R_SPARC_32:
   case R_SPARC_UA32:
     // V-word32
     checkUInt(ctx, loc, val, 32, rel);
     write32be(loc, val);
     break;
+  case R_SPARC_DISP8:
+    // V-byte8
+    checkIntUInt(ctx, loc, val, 8, rel);
+    *loc = val;
+    break;
+  case R_SPARC_DISP16:
+    // V-half16
+    checkIntUInt(ctx, loc, val, 16, rel);
+    write16be(loc, val);
+    break;
   case R_SPARC_DISP32:
     // V-disp32
-    checkInt(ctx, loc, val, 32, rel);
+    checkIntUInt(ctx, loc, val, 32, rel);
     write32be(loc, val);
     break;
   case R_SPARC_WDISP30:
   case R_SPARC_WPLT30:
+  case R_SPARC_TLS_GD_CALL:
+  case R_SPARC_TLS_LDM_CALL:
     // V-disp30
-    checkInt(ctx, loc, val, 32, rel);
+    checkIntUInt(ctx, loc, val, 32, rel);
     write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
     break;
+  case R_SPARC_WDISP22:
+    // V-disp22
+    checkIntUInt(ctx, loc, val, 24, rel);
+    write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 2) & 0x003fffff));
+    break;
+  case R_SPARC_HI22:
+    // V-imm22
+    checkUInt(ctx, loc, val, 32, rel);
+    write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
+    break;
   case R_SPARC_22:
     // V-imm22
     checkUInt(ctx, loc, val, 22, rel);
     write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));
     break;
+  case R_SPARC_13:
+  case R_SPARC_GOT13:
+    // V-simm13
+    checkIntUInt(ctx, loc, val, 13, rel);
+    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00001fff));
+    break;
+  case R_SPARC_LO10:
+  case R_SPARC_GOT10:
+  case R_SPARC_PC10:
+  case R_SPARC_TLS_GD_LO10:
+  case R_SPARC_TLS_LDM_LO10:
+  case R_SPARC_TLS_IE_LO10:
+    // T-simm13
+    write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));
+    break;
   case R_SPARC_GOT22:
-  case R_SPARC_PC22:
   case R_SPARC_LM22:
+  case R_SPARC_TLS_GD_HI22:
+  case R_SPARC_TLS_LDM_HI22:
+  case R_SPARC_TLS_LDO_HIX22:
+  case R_SPARC_TLS_IE_HI22:
     // T-imm22
     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
     break;
-  case R_SPARC_HI22:
-    // V-imm22
-    checkUInt(ctx, loc, val >> 10, 22, rel);
+  case R_SPARC_PC22:
+    // V-disp22
+    checkIntUInt(ctx, loc, val, 32, rel);
     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
     break;
-  case R_SPARC_WDISP19:
-    // V-disp19
-    checkInt(ctx, loc, val, 21, rel);
-    write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
-    break;
-  case R_SPARC_GOT10:
-  case R_SPARC_PC10:
-    // 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_DISP64:
   case R_SPARC_UA64:
     // V-xword64
     write64be(loc, val);
     break;
   case R_SPARC_HH22:
     // V-imm22
-    checkUInt(ctx, 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));
+    write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 32) & 0x000003ff));
+    break;
+  case R_SPARC_WDISP16:
+    // V-d2/disp14
+    checkIntUInt(ctx, loc, val, 18, rel);
+    write32be(loc, (read32be(loc) & ~0x0303fff) |
+                       (((val >> 2) & 0xc000) << 6) |
+                       ((val >> 2) & 0x00003fff));
+    break;
+  case R_SPARC_WDISP19:
+    // V-disp19
+    checkIntUInt(ctx, loc, val, 21, rel);
+    write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
+    break;
+  case R_SPARC_HIX22:
+    // V-imm22
+    checkUInt(ctx, loc, ~val, 32, rel);
+    write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
+    break;
+  case R_SPARC_LOX10:
+  case R_SPARC_TLS_LE_LOX10:
+  case R_SPARC_GOTDATA_LOX10:
+  case R_SPARC_GOTDATA_OP_LOX10:
+    // T-simm13
+    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1c00);
     break;
   case R_SPARC_H44:
     // V-imm22
-    checkUInt(ctx, loc, val >> 22, 22, rel);
+    checkUInt(ctx, loc, val, 44, rel);
     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff));
     break;
   case R_SPARC_M44:
@@ -219,21 +358,110 @@ void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
     break;
   case R_SPARC_L44:
     // T-imm13
-    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff));
+    write32be(loc, (read32be(loc) & ~0x00000fff) | (val & 0x00000fff));
+    break;
+  case R_SPARC_TLS_GD_ADD:
+  case R_SPARC_TLS_LDM_ADD:
+  case R_SPARC_TLS_LDO_ADD:
+  case R_SPARC_TLS_IE_LD:
+  case R_SPARC_TLS_IE_LDX:
+  case R_SPARC_TLS_IE_ADD:
     break;
   case R_SPARC_TLS_LE_HIX22:
     // T-imm22
     write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
     break;
-  case R_SPARC_TLS_LE_LOX10:
+  case R_SPARC_TLS_LDO_LOX10:
     // T-simm13
-    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);
+    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff));
+    break;
+  case R_SPARC_GOTDATA_HIX22:
+    // V-imm22
+    checkUInt(ctx, loc, ((int64_t)val < 0 ? ~val : val), 32, rel);
+    write32be(loc, (read32be(loc) & ~0x003fffff) |
+                       ((((int64_t)val < 0 ? ~val : val) >> 10) & 0x003fffff));
+    break;
+  case R_SPARC_GOTDATA_OP_HIX22:
+    // T-imm22
+    write32be(loc, (read32be(loc) & ~0x003fffff) |
+                       ((((int64_t)val < 0 ? ~val : val) >> 10) & 0x003fffff));
+    break;
+  case R_SPARC_GOTDATA_OP:
     break;
   default:
     llvm_unreachable("unknown relocation");
   }
 }
 
+RelExpr SPARCV9::adjustGotOffExpr(RelType type, const Symbol &sym,
+                                  int64_t addend, const uint8_t *loc) const {
+  switch (type) {
+  case R_SPARC_GOTDATA_OP_HIX22:
+  case R_SPARC_GOTDATA_OP_LOX10:
+  case R_SPARC_GOTDATA_OP:
+    if (sym.isLocal())
+      return R_RELAX_GOT_OFF;
+    [[fallthrough]];
+  default:
+    return R_GOT_OFF;
+  }
+}
+
+void SPARCV9::relaxGot(uint8_t *loc, const Relocation &rel,
+                       uint64_t val) const {
+  switch (rel.type) {
+  case R_SPARC_GOTDATA_OP_HIX22:
+    // T-imm22
+    write32be(loc, (read32be(loc) & ~0x003fffff) |
+                       ((((int64_t)val < 0 ? ~val : val) >> 10) & 0x003fffff));
+    break;
+  case R_SPARC_GOTDATA_OP_LOX10:
+    // T-imm13
+    write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) |
+                       ((int64_t)val < 0 ? 0x1c00 : 0));
+    break;
+  case R_SPARC_GOTDATA_OP:
+    // ldx [%rs1 + %rs2], %rd -> add %rs1, %rs2, %rd
+    write32be(loc, (read32be(loc) & 0x3e07c01f) | 0x80000000);
+    break;
+  default:
+    llvm_unreachable("unknown relocation");
+  }
+}
+
+void SPARCV9::writeGotHeader(uint8_t *buf) const {
+  write64be(buf, ctx.in.dynamic->getVA());
+}
+
+static bool isTlsCall(RelType type) {
+  return type == R_SPARC_TLS_GD_CALL || type == R_SPARC_TLS_LDM_CALL;
+}
+
+void SPARCV9::finalizeRelocScan() {
+  Symbol *tga = nullptr;
+
+  for (ELFFileBase *file : ctx.objectFiles) {
+    for (InputSectionBase *s : file->getSections()) {
+      auto *isec = dyn_cast_or_null<InputSection>(s);
+      if (!isec || !isec->isLive())
+        continue;
+      for (Relocation &rel : isec->relocs()) {
+        if (rel.expr != R_PLT_PC || !isTlsCall(rel.type))
+          continue;
+        if (!tga) {
+          tga = ctx.symtab->addSymbol(Undefined{ctx.internalFile,
+                                                "__tls_get_addr", STB_GLOBAL,
+                                                STV_DEFAULT, STT_FUNC});
+          tga->isUsedInRegularObj = true;
+          tga->isPreemptible = true;
+          tga->setFlags(NEEDS_PLT | USED);
+        }
+        rel.sym = tga;
+      }
+    }
+  }
+}
+
 void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/,
                        uint64_t pltEntryAddr) const {
   const uint8_t pltData[] = {
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7ec7dfcae6bca..a2552a1ae1ab7 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1318,9 +1318,10 @@ static SmallVector<StringRef, 0> getSymbolOrderingFile(Ctx &ctx,
 
 static bool getIsRela(Ctx &ctx, opt::InputArgList &args) {
   // The psABI specifies the default relocation entry format.
-  bool rela = is_contained({EM_AARCH64, EM_AMDGPU, EM_HEXAGON, EM_LOONGARCH,
-                            EM_PPC, EM_PPC64, EM_RISCV, EM_S390, EM_X86_64},
-                           ctx.arg.emachine);
+  bool rela =
+      is_contained({EM_AARCH64, EM_AMDGPU, EM_HEXAGON, EM_LOONGARCH, EM_PPC,
+                    EM_PPC64, EM_RISCV, EM_S390, EM_SPARCV9, EM_X86_64},
+                   ctx.arg.emachine);
   // If -z rel or -z rela is specified, use the last option.
   for (auto *arg : args.filtered(OPT_z)) {
     StringRef s(arg->getValue());
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index c78800787d27e..c26425bbc4a7b 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -833,6 +833,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
   case R_GOTPLTONLY_PC:
     return ctx.in.gotPlt->getVA() + a - p;
   case R_GOTREL:
+  case R_RELAX_GOT_OFF:
     return r.sym->getVA(ctx, a) - ctx.in.got->getVA();
   case R_GOTPLTREL:
     return r.sym->getVA(ctx, a) - ctx.in.gotPlt->getVA();
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 0d45236e6d11e..cd8d3634e9d33 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -145,7 +145,7 @@ bool lld::elf::needsGot(RelExpr expr) {
 static bool isRelExpr(RelExpr expr) {
   return oneof<R_PC, R_GOTREL, R_GOTPLTREL, RE_ARM_PCA, RE_MIPS_GOTREL,
                RE_PPC64_CALL, RE_AARCH64_PAGE_PC, R_RELAX_GOT_PC,
-               RE_RISCV_PC_INDIRECT, RE_LOONGARCH_PAGE_PC,
+               R_RELAX_GOT_OFF, RE_RISCV_PC_INDIRECT, RE_LOONGARCH_PAGE_PC,
                RE_LOONGARCH_PC_INDIRECT>(expr);
 }
 
@@ -747,14 +747,16 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
 template <class PltSection, class GotPltSection>
 static void addPltEntry(Ctx &ctx, PltSection &plt, GotPltSection &gotPlt,
                         RelocationBaseSection &rel, RelType type, Symbol &sym) {
+  RelExpr expr = sym.isPreemptible ? R_ADDEND : R_ABS;
   plt.addEntry(sym);
-  gotPlt.addEntry(sym);
-  if (sym.isPreemptible)
-    rel.addReloc(
-        {type, &gotPlt, sym.getGotPltOffset(ctx), true, sym, 0, R_ADDEND});
-  else
-    rel.addReloc(
-        {type, &gotPlt, sym.getGotPltOffset(ctx), false, sym, 0, R_ABS});
+  if (ctx.target->usesGotPlt) {
+    gotPlt.addEntry(sym);
+    rel.addReloc({type, &gotPlt, sym.getGotPltOffset(ctx), sym.isPreemptible,
+                  sym, 0, expr});
+  } else {
+    rel.addReloc({type, &plt, sym.getPltOffset(ctx), sym.isPreemptible, sym, 0,
+                  expr});
+  }
 }
 
 void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
@@ -920,14 +922,19 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
   // indirection.
   const bool isIfunc = sym.isGnuIFunc();
   if (!sym.isPreemptible && !isIfunc) {
-    if (expr != R_GOT_PC) {
+    if (expr != R_GOT_PC && expr != R_GOT_OFF) {
       expr = fromPlt(expr);
     } else if (!isAbsoluteOrTls(sym)) {
-      expr = ctx.target->adjustGotPcExpr(type, addend,
-                                         sec->content().data() + offset);
-      // If the target adjusted the expression to R_RELAX_GOT_PC, we may end up
+      if (expr == R_GOT_PC)
+        expr = ctx.target->adjustGotPcExpr(type, addend,
+                                           sec->content().data() + offset);
+      else
+        expr = ctx.target->adjustGotOffExpr(type, sym, addend,
+                                            sec->content().data() + offset);
+
+      // If the target adjusted the expression to R_RELAX_GOT_*, we may end up
       // needing the GOT if we can't relax everything.
-      if (expr == R_RELAX_GOT_PC)
+      if (expr == R_RELAX_GOT_PC || expr == R_RELAX_GOT_OFF)
         ctx.in.got->hasGotOffRel.store(true, std::memory_order_relaxed);
     }
   }
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index abc62bf01a421..210ef5efb4a07 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -61,6 +61,7 @@ enum RelExpr {
   R_PLT_GOTPLT,
   R_PLT_GOTREL,
   R_RELAX_HINT,
+  R_RELAX_GOT_OFF,
   R_RELAX_GOT_PC,
   R_RELAX_GOT_PC_NOPIC,
   R_RELAX_TLS_GD_TO_IE,
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 7bad4ceccec33..67e07b840cb82 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -181,6 +181,12 @@ uint64_t Symbol::getGotPltOffset(Ctx &ctx) const {
          ctx.target->gotEntrySize;
 }
 
+uint64_t Symbol::getPltOffset(Ctx &ctx) const {
+  if (isInIplt)
+    return getPltIdx(ctx) * ctx.target->ipltEntrySize;
+  return ctx.in.plt->headerSize + getPltIdx(ctx) * ctx.target->pltEntrySize;
+}
+
 uint64_t Symbol::getPltVA(Ctx &ctx) const {
   uint64_t outVA = isInIplt ? ctx.in.iplt->getVA() +
                                   getPltIdx(ctx) * ctx.target->ipltEntrySize
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index b7d0b13ae476c..0893776882dc6 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -198,6 +198,7 @@ class Symbol {
   uint64_t getGotVA(Ctx &) const;
   uint64_t getGotPltOffset(Ctx &) const;
   uint64_t getGotPltVA(Ctx &) const;
+  uint64_t getPltOffset(Ctx &) const;
   uint64_t getPltVA(Ctx &) const;
   uint64_t getSize() const;
   OutputSection *getOutputSection() const;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b9a42590dc8e7..aa5fabe9f9cbc 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1523,14 +1523,31 @@ void RelocationBaseSection::finalizeContents() {
   else
     getParent()->link = 0;
 
-  if (ctx.in.relaPlt.get() == this && ctx.in.gotPlt->getParent()) {
-    getParent()->flags |= ELF::SHF_INFO_LINK;
-    getParent()->info = ctx.in.gotPlt->getParent()->sectionIndex;
+  if (ctx.in.relaPlt.get() == this) {
+    if (ctx.target->usesGotPlt && ctx.in.gotPlt->getParent()) {
+      getParent()->flags |= ELF::SHF_INFO_LINK;
+      getParent()->info = ctx.in.gotPlt->getParent()->sectionIndex;
+    } else if (ctx.in.plt->getParent()) {
+      getParent()->flags |= ELF::SHF_INFO_LINK;
+      getParent()->info = ctx.in.plt->getParent()->sectionIndex;
+    }
   }
 }
 
 void DynamicReloc::finalize(Ctx &ctx, SymbolTableBaseSect...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/207609


More information about the llvm-commits mailing list