Index: lld/ELF/Relocations.cpp
--- lld/ELF/Relocations.cpp.orig
+++ lld/ELF/Relocations.cpp
@@ -54,6 +54,29 @@ static void printDefinedLocation(ELFSyncStream &s, con
   s << "\n>>> defined in " << sym.file;
 }
 
+void elf::reportGNUWarning(Ctx &ctx, Symbol &sym, InputSectionBase &sec,
+                                 uint64_t offset) {
+  std::lock_guard<std::mutex> lock(ctx.relocMutex);
+  if (sym.gwarn) {
+    StringRef gnuWarning = gnuWarnings.lookup(sym.getName());
+    ELFSyncStream msg(ctx, DiagLevel::None);
+    // report first occurance only
+    sym.gwarn = false;
+    if (!gnuWarning.empty()) {
+      msg << sec.getSrcMsg(sym, offset);
+      msg << "(";
+      msg << sec.getObjMsg(offset);
+      msg << "): warning: ";
+      msg << gnuWarning;
+#if 0
+      warn(sec.getSrcMsg(sym, offset) + "(" + sec.getObjMsg(offset) +
+           "): warning: " + gnuWarning);
+#endif
+      Warn(ctx) << msg.str();
+    }
+  }
+}
+
 // Construct a message in the following format.
 //
 // >>> defined in /home/alice/src/foo.o
@@ -147,8 +170,9 @@ 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_PPC64_RELAX_TOC, RE_AARCH64_PAGE_PC,
-               R_RELAX_GOT_PC, RE_RISCV_PC_INDIRECT, RE_PPC64_RELAX_GOT_PC,
-               RE_LOONGARCH_PAGE_PC, RE_LOONGARCH_PC_INDIRECT>(expr);
+               R_RELAX_GOT_OFF, R_RELAX_GOT_PC, RE_RISCV_PC_INDIRECT,
+               RE_PPC64_RELAX_GOT_PC, RE_LOONGARCH_PAGE_PC,
+               RE_LOONGARCH_PC_INDIRECT>(expr);
 }
 
 static RelExpr toPlt(RelExpr expr) {
@@ -682,6 +706,13 @@ bool RelocScan::maybeReportUndefined(Undefined &sym, u
   if (sym.discardedSecIdx != 0 && (sec->name == ".got2" || sec->name == ".toc"))
     return false;
 
+#ifdef __OpenBSD__
+  // GCC (at least 8 and 11) can produce a ".gcc_except_table" with relocations
+  // to discarded sections on riscv64
+  if (sym.discardedSecIdx != 0 && sec->name == ".gcc_except_table")
+    return false;
+#endif
+
   bool isWarning =
       (ctx.arg.unresolvedSymbols == UnresolvedPolicy::Warn && canBeExternal) ||
       ctx.arg.noinhibitExec;
@@ -740,14 +771,18 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBas
 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)
+  if (ctx.target->usesGotPlt) {
+    gotPlt.addEntry(sym);
+    // The relocation is applied to the .got.plt entry.
+    rel.addReloc({type, &gotPlt, sym.getGotPltOffset(ctx), !!sym.isPreemptible,
+                  sym, 0, expr});
+  } else {
+    // The relocation is applied to the .plt entry.
     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});
+        {type, &plt, sym.getPltOffset(ctx), !!sym.isPreemptible, sym, 0, expr});
+  }
 }
 
 void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
@@ -915,25 +950,32 @@ void RelocScan::process(RelExpr expr, RelType type, ui
   // indirection.
   const bool isIfunc = sym.isGnuIFunc();
   if (!sym.isPreemptible && (!isIfunc || ctx.arg.zIfuncNoplt)) {
-    if (expr != R_GOT_PC) {
+    if (expr != R_GOT_PC && expr != R_GOT_OFF) {
       // The 0x8000 bit of r_addend of R_PPC_PLTREL24 is used to choose call
       // stub type. It should be ignored if optimized to R_PC.
       if (ctx.arg.emachine == EM_PPC && expr == RE_PPC32_PLTREL)
         addend &= ~0x8000;
       // R_HEX_GD_PLT_B22_PCREL (call a@GDPLT) is transformed into
       // call __tls_get_addr even if the symbol is non-preemptible.
+      // Same deal for R_SPARC_TLS_LDM_CALL (call x@TLSPLT).
       if (!(ctx.arg.emachine == EM_HEXAGON &&
             (type == R_HEX_GD_PLT_B22_PCREL ||
              type == R_HEX_GD_PLT_B22_PCREL_X ||
-             type == R_HEX_GD_PLT_B32_PCREL_X)))
+             type == R_HEX_GD_PLT_B32_PCREL_X)) &&
+          !(ctx.arg.emachine == EM_SPARCV9 && type == R_SPARC_TLS_LDM_CALL))
         expr = fromPlt(expr);
     } else if (!isAbsoluteValue(sym) ||
                (type == R_PPC64_PCREL_OPT && ctx.arg.emachine == EM_PPC64)) {
-      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 if (expr == R_GOT_OFF)
+        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);
     }
   }
@@ -992,8 +1034,14 @@ void RelocScan::process(RelExpr expr, RelType type, ui
                     (isa<EhInputSection>(sec) && ctx.arg.emachine != EM_MIPS));
   if (canWrite) {
     RelType rel = ctx.target->getDynRel(type);
-    if (oneof<R_GOT, RE_LOONGARCH_GOT>(expr) ||
-        (rel == ctx.target->symbolicRel && !sym.isPreemptible)) {
+    bool useRelative =
+        rel == ctx.target->symbolicRel && !sym.isPreemptible;
+    if (ctx.arg.emachine == EM_SPARCV9 &&
+        (type == R_SPARC_16 || type == R_SPARC_32 || type == R_SPARC_64 ||
+         type == R_SPARC_UA16 || type == R_SPARC_UA32 ||
+         type == R_SPARC_UA64))
+      useRelative = false;
+    if (oneof<R_GOT, RE_LOONGARCH_GOT>(expr) || useRelative) {
       addRelativeReloc<true>(ctx, *sec, offset, sym, addend, expr, type);
       return;
     }
@@ -1036,6 +1084,7 @@ void RelocScan::process(RelExpr expr, RelType type, ui
           return;
         }
       }
+      ctx.target->prepareDynamicReloc(rel, sym, *sec);
       part.relaDyn->addSymbolReloc(rel, *sec, offset, sym, addend, type);
 
       // MIPS ABI turns using of GOT and dynamic relocations inside out.
@@ -1206,12 +1255,13 @@ unsigned RelocScan::handleTlsRelocation(RelExpr expr, 
 
   // ARM, Hexagon, LoongArch and RISC-V do not support GD/LD to IE/LE
   // optimizations.
+  // SPARC support for GD/LD to IE/LE optimizations is not yet implemented.
   // RISC-V supports TLSDESC to IE/LE optimizations.
   // For PPC64, if the file has missing R_PPC64_TLSGD/R_PPC64_TLSLD, disable
   // optimization as well.
   bool execOptimize =
       !ctx.arg.shared && ctx.arg.emachine != EM_ARM &&
-      ctx.arg.emachine != EM_HEXAGON &&
+      ctx.arg.emachine != EM_HEXAGON && ctx.arg.emachine != EM_SPARCV9 &&
       (ctx.arg.emachine != EM_LOONGARCH || execOptimizeInLoongArch) &&
       !(isRISCV && expr != R_TLSDESC_PC && expr != R_TLSDESC_CALL) &&
       !sec->file->ppc64DisableTLSRelax;
@@ -1555,10 +1605,7 @@ void elf::postScanRelocations(Ctx &ctx) {
       } else {
         assert(sym.isFunc() && sym.hasFlag(NEEDS_PLT));
         if (!sym.isDefined()) {
-          replaceWithDefined(ctx, sym, *ctx.in.plt,
-                             ctx.target->pltHeaderSize +
-                                 ctx.target->pltEntrySize * sym.getPltIdx(ctx),
-                             0);
+          replaceWithDefined(ctx, sym, *ctx.in.plt, sym.getPltOffset(ctx), 0);
           sym.setFlags(NEEDS_COPY);
           if (ctx.arg.emachine == EM_PPC) {
             // PPC32 canonical PLT entries are at the beginning of .glink
@@ -2203,11 +2250,11 @@ bool ThunkCreator::createThunks(uint32_t pass,
   return addressesChanged;
 }
 
-// The following aid in the conversion of call x@GDPLT to call __tls_get_addr
-// hexagonNeedsTLSSymbol scans for relocations would require a call to
-// __tls_get_addr.
-// hexagonTLSSymbolUpdate rebinds the relocation to __tls_get_addr.
-bool elf::hexagonNeedsTLSSymbol(ArrayRef<OutputSection *> outputSections) {
+// The following aid in the conversion of call x@GDPLT (Hexagon) and
+// call x@TLSPLT (SPARC) to call __tls_get_addr. needsTLSSymbol scans
+// for relocations that would require a call to __tls_get_addr.
+// tlsSymbolUpdate rebinds the relocation to __tls_get_addr.
+bool elf::needsTLSSymbol(ArrayRef<OutputSection *> outputSections) {
   bool needTlsSymbol = false;
   forEachInputSectionDescription(
       outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
@@ -2221,7 +2268,7 @@ bool elf::hexagonNeedsTLSSymbol(ArrayRef<OutputSection
   return needTlsSymbol;
 }
 
-void elf::hexagonTLSSymbolUpdate(Ctx &ctx) {
+void elf::tlsSymbolUpdate(Ctx &ctx) {
   Symbol *sym = ctx.symtab->find("__tls_get_addr");
   if (!sym)
     return;
