[lld] 685507d - Revert "[ELF] Add target-specific relocation scanning for x86" (#181274)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 12 20:03:22 PST 2026


Author: Andrew Lazarev
Date: 2026-02-12T20:03:17-08:00
New Revision: 685507d9beefce91a59591795a54bf92b66c8de7

URL: https://github.com/llvm/llvm-project/commit/685507d9beefce91a59591795a54bf92b66c8de7
DIFF: https://github.com/llvm/llvm-project/commit/685507d9beefce91a59591795a54bf92b66c8de7.diff

LOG: Revert "[ELF] Add target-specific relocation scanning for x86" (#181274)

Reverts llvm/llvm-project#178846

Brakes buildbot:
https://lab.llvm.org/buildbot/#/builders/25/builds/15566

Added: 
    

Modified: 
    lld/ELF/Arch/X86.cpp
    lld/ELF/Arch/X86_64.cpp
    lld/ELF/RelocScan.h
    lld/ELF/Relocations.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/X86.cpp b/lld/ELF/Arch/X86.cpp
index 1857792c99ab1..904741fd72b0a 100644
--- a/lld/ELF/Arch/X86.cpp
+++ b/lld/ELF/Arch/X86.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "OutputSections.h"
-#include "RelocScan.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
@@ -23,6 +22,7 @@ namespace {
 class X86 : public TargetInfo {
 public:
   X86(Ctx &);
+  int getTlsGdRelaxSkip(RelType type) const override;
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
   int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
@@ -35,9 +35,8 @@ class X86 : public TargetInfo {
                 uint64_t pltEntryAddr) const override;
   void relocate(uint8_t *loc, const Relocation &rel,
                 uint64_t val) const override;
-  template <class ELFT, class RelTy>
-  void scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels);
-  void scanSection(InputSectionBase &sec) override;
+
+  RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
   void relocateAlloc(InputSection &sec, uint8_t *buf) const override;
 
 private:
@@ -70,7 +69,11 @@ X86::X86(Ctx &ctx) : TargetInfo(ctx) {
   defaultImageBase = 0x400000;
 }
 
-// Only needed to support relocations used by relocateNonAlloc.
+int X86::getTlsGdRelaxSkip(RelType type) const {
+  // TLSDESC relocations are processed separately. See relaxTlsGdToLe below.
+  return type == R_386_TLS_GOTDESC || type == R_386_TLS_DESC_CALL ? 1 : 2;
+}
+
 RelExpr X86::getRelExpr(RelType type, const Symbol &s,
                         const uint8_t *loc) const {
   switch (type) {
@@ -80,6 +83,10 @@ RelExpr X86::getRelExpr(RelType type, const Symbol &s,
     return R_ABS;
   case R_386_TLS_LDO_32:
     return R_DTPREL;
+  case R_386_TLS_GD:
+    return R_TLSGD_GOTPLT;
+  case R_386_TLS_LDM:
+    return R_TLSLD_GOTPLT;
   case R_386_PLT32:
     return R_PLT_PC;
   case R_386_PC8:
@@ -88,6 +95,52 @@ RelExpr X86::getRelExpr(RelType type, const Symbol &s,
     return R_PC;
   case R_386_GOTPC:
     return R_GOTPLTONLY_PC;
+  case R_386_TLS_IE:
+    return R_GOT;
+  case R_386_GOT32:
+  case R_386_GOT32X:
+    // These relocations are arguably mis-designed because their calculations
+    // depend on the instructions they are applied to. This is bad because we
+    // usually don't care about whether the target section contains valid
+    // machine instructions or not. But this is part of the documented ABI, so
+    // we had to implement as the standard requires.
+    //
+    // x86 does not support PC-relative data access. Therefore, in order to
+    // access GOT contents, a GOT address needs to be known at link-time
+    // (which means non-PIC) or compilers have to emit code to get a GOT
+    // address at runtime (which means code is position-independent but
+    // compilers need to emit extra code for each GOT access.) This decision
+    // is made at compile-time. In the latter case, compilers emit code to
+    // load a GOT address to a register, which is usually %ebx.
+    //
+    // So, there are two ways to refer to symbol foo's GOT entry: foo at GOT or
+    // foo at GOT(%ebx).
+    //
+    // foo at GOT is not usable in PIC. If we are creating a PIC output and if we
+    // find such relocation, we should report an error. foo at GOT is resolved to
+    // an *absolute* address of foo's GOT entry, because both GOT address and
+    // foo's offset are known. In other words, it's G + A.
+    //
+    // foo at GOT(%ebx) needs to be resolved to a *relative* offset from a GOT to
+    // foo's GOT entry in the table, because GOT address is not known but foo's
+    // offset in the table is known. It's G + A - GOT.
+    //
+    // It's unfortunate that compilers emit the same relocation for these
+    // 
diff erent use cases. In order to distinguish them, we have to read a
+    // machine instruction.
+    //
+    // The following code implements it. We assume that Loc[0] is the first byte
+    // of a displacement or an immediate field of a valid machine
+    // instruction. That means a ModRM byte is at Loc[-1]. By taking a look at
+    // the byte, we can determine whether the instruction uses the operand as an
+    // absolute address (R_GOT) or a register-relative address (R_GOTPLT).
+    return (loc[-1] & 0xc7) == 0x5 ? R_GOT : R_GOTPLT;
+  case R_386_TLS_GOTDESC:
+    return R_TLSDESC_GOTPLT;
+  case R_386_TLS_DESC_CALL:
+    return R_TLSDESC_CALL;
+  case R_386_TLS_GOTIE:
+    return R_GOTPLT;
   case R_386_GOTOFF:
     return R_GOTPLTREL;
   case R_386_TLS_LE:
@@ -103,6 +156,18 @@ RelExpr X86::getRelExpr(RelType type, const Symbol &s,
   }
 }
 
+RelExpr X86::adjustTlsExpr(RelType type, RelExpr expr) const {
+  switch (expr) {
+  default:
+    return expr;
+  case R_RELAX_TLS_GD_TO_IE:
+    return R_RELAX_TLS_GD_TO_IE_GOTPLT;
+  case R_RELAX_TLS_GD_TO_LE:
+    return type == R_386_TLS_GD ? R_RELAX_TLS_GD_TO_LE_NEG
+                                : R_RELAX_TLS_GD_TO_LE;
+  }
+}
+
 void X86::writeGotPltHeader(uint8_t *buf) const {
   write32le(buf, ctx.mainPart->dynamic->getVA());
 }
@@ -173,125 +238,6 @@ void X86::writePlt(uint8_t *buf, const Symbol &sym,
   write32le(buf + 12, ctx.in.plt->getVA() - pltEntryAddr - 16);
 }
 
-template <class ELFT, class RelTy>
-void X86::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
-  RelocScan rs(ctx, &sec);
-  sec.relocations.reserve(rels.size());
-
-  for (auto it = rels.begin(); it != rels.end(); ++it) {
-    const RelTy &rel = *it;
-    uint32_t symIdx = rel.getSymbol(false);
-    Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIdx);
-    uint64_t offset = rel.r_offset;
-    RelType type = rel.getType(false);
-    if (sym.isUndefined() && symIdx != 0 &&
-        rs.maybeReportUndefined(cast<Undefined>(sym), offset))
-      continue;
-    int64_t addend = rs.getAddend<ELFT>(rel, type);
-    RelExpr expr;
-    switch (type) {
-    case R_386_NONE:
-      continue;
-
-      // Absolute relocations:
-    case R_386_8:
-    case R_386_16:
-    case R_386_32:
-      expr = R_ABS;
-      break;
-
-      // PC-relative relocations:
-    case R_386_PC8:
-    case R_386_PC16:
-    case R_386_PC32:
-      rs.processR_PC(type, offset, addend, sym);
-      continue;
-
-      // PLT-generating relocation:
-    case R_386_PLT32:
-      rs.processR_PLT_PC(type, offset, addend, sym);
-      continue;
-
-      // GOT-related relocations:
-    case R_386_GOTPC:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      expr = R_GOTPLTONLY_PC;
-      break;
-    case R_386_GOTOFF:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      expr = R_GOTPLTREL;
-      break;
-    case R_386_GOT32:
-    case R_386_GOT32X:
-      // R_386_GOT32(X) is used for both absolute GOT access (foo at GOT,
-      // non-PIC, G + A => R_GOT) and register-relative GOT access
-      // (foo at GOT(%ebx), PIC, G + A - GOT => R_GOTPLT). Both use the same
-      // relocation type, so we check the ModRM byte to distinguish them.
-      expr =
-          (sec.content().data()[offset - 1] & 0xc7) == 0x5 ? R_GOT : R_GOTPLT;
-      if (expr == R_GOTPLT)
-        ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      break;
-
-      // TLS relocations:
-    case R_386_TLS_LE:
-      if (rs.checkTlsLe(offset, sym, type))
-        continue;
-      expr = R_TPREL;
-      break;
-    case R_386_TLS_LE_32:
-      if (rs.checkTlsLe(offset, sym, type))
-        continue;
-      expr = R_TPREL_NEG;
-      break;
-    case R_386_TLS_IE:
-      rs.handleTlsIe(R_GOT, type, offset, addend, sym);
-      continue;
-    case R_386_TLS_GOTIE:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      rs.handleTlsIe(R_GOTPLT, type, offset, addend, sym);
-      continue;
-    case R_386_TLS_GD:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      // Use R_TPREL_NEG for negative TP offset.
-      if (rs.handleTlsGd(R_TLSGD_GOTPLT, R_GOTPLT, R_TPREL_NEG, type, offset,
-                         addend, sym))
-        ++it;
-      continue;
-    case R_386_TLS_LDM:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      if (rs.handleTlsLd(R_TLSLD_GOTPLT, type, offset, addend, sym))
-        ++it;
-      continue;
-    case R_386_TLS_LDO_32:
-      sec.addReloc(
-          {ctx.arg.shared ? R_DTPREL : R_TPREL, type, offset, addend, &sym});
-      continue;
-    case R_386_TLS_GOTDESC:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      rs.handleTlsDesc(R_TLSDESC_GOTPLT, R_GOTPLT, type, offset, addend, sym);
-      continue;
-    case R_386_TLS_DESC_CALL:
-      // For executables, TLSDESC is optimized to IE or LE. Use R_TPREL as the
-      // rewrites for this relocation are identical.
-      if (!ctx.arg.shared)
-        sec.addReloc({R_TPREL, type, offset, addend, &sym});
-      continue;
-
-    default:
-      Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset)
-               << "unknown relocation (" << type.v << ") against symbol "
-               << &sym;
-      continue;
-    }
-    rs.process(expr, type, offset, sym, addend);
-  }
-}
-
-void X86::scanSection(InputSectionBase &sec) {
-  elf::scanSection1<X86, ELF32LE>(*this, sec);
-}
-
 int64_t X86::getImplicitAddend(const uint8_t *buf, RelType type) const {
   switch (type) {
   case R_386_8:
@@ -465,6 +411,11 @@ void X86::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
     }
     loc[-2] = 0x8b;
     write32le(loc, val);
+  } else {
+    // Convert call *x at tlsdesc(%eax) to xchg ax, ax.
+    assert(rel.type == R_386_TLS_DESC_CALL);
+    loc[0] = 0x66;
+    loc[1] = 0x90;
   }
 }
 
@@ -546,30 +497,19 @@ void X86::relocateAlloc(InputSection &sec, uint8_t *buf) const {
     uint8_t *loc = buf + rel.offset;
     const uint64_t val =
         SignExtend64(sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), 32);
-    switch (rel.type) {
-    case R_386_TLS_GD:
-    case R_386_TLS_GOTDESC:
-    case R_386_TLS_DESC_CALL:
-      if (rel.expr == R_TPREL || rel.expr == R_TPREL_NEG)
-        relaxTlsGdToLe(loc, rel, val);
-      else if (rel.expr == R_GOTPLT)
-        relaxTlsGdToIe(loc, rel, val);
-      else
-        relocate(loc, rel, val);
+    switch (rel.expr) {
+    case R_RELAX_TLS_GD_TO_IE_GOTPLT:
+      relaxTlsGdToIe(loc, rel, val);
       continue;
-    case R_386_TLS_LDM:
-    case R_386_TLS_LDO_32:
-      if (rel.expr == R_TPREL)
-        relaxTlsLdToLe(loc, rel, val);
-      else
-        relocate(loc, rel, val);
+    case R_RELAX_TLS_GD_TO_LE:
+    case R_RELAX_TLS_GD_TO_LE_NEG:
+      relaxTlsGdToLe(loc, rel, val);
       continue;
-    case R_386_TLS_IE:
-    case R_386_TLS_GOTIE:
-      if (rel.expr == R_TPREL)
-        relaxTlsIeToLe(loc, rel, val);
-      else
-        relocate(loc, rel, val);
+    case R_RELAX_TLS_LD_TO_LE:
+      relaxTlsLdToLe(loc, rel, val);
+      break;
+    case R_RELAX_TLS_IE_TO_LE:
+      relaxTlsIeToLe(loc, rel, val);
       continue;
     default:
       relocate(loc, rel, val);

diff  --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index 2671451d5b25c..bfdc281dfca3a 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "OutputSections.h"
-#include "RelocScan.h"
 #include "Relocations.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
@@ -28,6 +27,7 @@ namespace {
 class X86_64 : public TargetInfo {
 public:
   X86_64(Ctx &);
+  int getTlsGdRelaxSkip(RelType type) const override;
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
   RelType getDynRel(RelType type) const override;
@@ -51,9 +51,6 @@ class X86_64 : public TargetInfo {
                              InputSection *nextIS) const override;
   bool relaxOnce(int pass) const override;
   void applyBranchToBranchOpt() const override;
-  template <class ELFT, class RelTy>
-  void scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels);
-  void scanSection(InputSectionBase &sec) override;
 
 private:
   void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
@@ -101,6 +98,15 @@ X86_64::X86_64(Ctx &ctx) : TargetInfo(ctx) {
   defaultImageBase = 0x200000;
 }
 
+int X86_64::getTlsGdRelaxSkip(RelType type) const {
+  // TLSDESC relocations are processed separately. See relaxTlsGdToLe below.
+  return type == R_X86_64_GOTPC32_TLSDESC ||
+                 type == R_X86_64_CODE_4_GOTPC32_TLSDESC ||
+                 type == R_X86_64_TLSDESC_CALL
+             ? 1
+             : 2;
+}
+
 // Opcodes for the 
diff erent X86_64 jmp instructions.
 enum JmpInsnOpcode : uint32_t {
   J_JMP_32,
@@ -355,7 +361,6 @@ bool X86_64::relaxOnce(int pass) const {
   return changed;
 }
 
-// Only needed to support relocations used by relocateNonAlloc and relocateEH.
 RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
                            const uint8_t *loc) const {
   switch (type) {
@@ -365,15 +370,21 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
   case R_X86_64_32S:
   case R_X86_64_64:
     return R_ABS;
-  case R_X86_64_SIZE32:
-  case R_X86_64_SIZE64:
-    return R_SIZE;
   case R_X86_64_DTPOFF32:
   case R_X86_64_DTPOFF64:
     return R_DTPREL;
   case R_X86_64_TPOFF32:
   case R_X86_64_TPOFF64:
     return R_TPREL;
+  case R_X86_64_TLSDESC_CALL:
+    return R_TLSDESC_CALL;
+  case R_X86_64_TLSLD:
+    return R_TLSLD_PC;
+  case R_X86_64_TLSGD:
+    return R_TLSGD_PC;
+  case R_X86_64_SIZE32:
+  case R_X86_64_SIZE64:
+    return R_SIZE;
   case R_X86_64_PLT32:
     return R_PLT_PC;
   case R_X86_64_PC8:
@@ -381,8 +392,24 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
   case R_X86_64_PC32:
   case R_X86_64_PC64:
     return R_PC;
+  case R_X86_64_GOT32:
+  case R_X86_64_GOT64:
+    return R_GOTPLT;
+  case R_X86_64_GOTPC32_TLSDESC:
+  case R_X86_64_CODE_4_GOTPC32_TLSDESC:
+    return R_TLSDESC_PC;
+  case R_X86_64_GOTPCREL:
+  case R_X86_64_GOTPCRELX:
+  case R_X86_64_REX_GOTPCRELX:
+  case R_X86_64_CODE_4_GOTPCRELX:
+  case R_X86_64_GOTTPOFF:
+  case R_X86_64_CODE_4_GOTTPOFF:
+  case R_X86_64_CODE_6_GOTTPOFF:
+    return R_GOT_PC;
   case R_X86_64_GOTOFF64:
     return R_GOTPLTREL;
+  case R_X86_64_PLTOFF64:
+    return R_PLT_GOTPLT;
   case R_X86_64_GOTPC32:
   case R_X86_64_GOTPC64:
     return R_GOTPLTONLY_PC;
@@ -448,138 +475,6 @@ RelType X86_64::getDynRel(RelType type) const {
   return R_X86_64_NONE;
 }
 
-template <class ELFT, class RelTy>
-void X86_64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
-  RelocScan rs(ctx, &sec);
-  sec.relocations.reserve(rels.size());
-
-  for (auto it = rels.begin(); it != rels.end(); ++it) {
-    const RelTy &rel = *it;
-    uint32_t symIdx = rel.getSymbol(false);
-    Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIdx);
-    uint64_t offset = rel.r_offset;
-    RelType type = rel.getType(false);
-    if (sym.isUndefined() && symIdx != 0 &&
-        rs.maybeReportUndefined(cast<Undefined>(sym), offset))
-      continue;
-    int64_t addend = rs.getAddend<ELFT>(rel, type);
-    RelExpr expr;
-    switch (type) {
-    case R_X86_64_NONE:
-      continue;
-
-      // Absolute relocations:
-    case R_X86_64_8:
-    case R_X86_64_16:
-    case R_X86_64_32:
-    case R_X86_64_32S:
-    case R_X86_64_64:
-      expr = R_ABS;
-      break;
-
-      // PC-relative relocations:
-    case R_X86_64_PC8:
-    case R_X86_64_PC16:
-    case R_X86_64_PC32:
-    case R_X86_64_PC64:
-      rs.processR_PC(type, offset, addend, sym);
-      continue;
-
-      // GOT-generating relocations:
-    case R_X86_64_GOTPC32:
-    case R_X86_64_GOTPC64:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      expr = R_GOTPLTONLY_PC;
-      break;
-    case R_X86_64_GOTOFF64:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      expr = R_GOTPLTREL;
-      break;
-    case R_X86_64_GOT32:
-    case R_X86_64_GOT64:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      expr = R_GOTPLT;
-      break;
-    case R_X86_64_PLTOFF64:
-      ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
-      expr = R_PLT_GOTPLT;
-      break;
-    case R_X86_64_GOTPCREL:
-    case R_X86_64_GOTPCRELX:
-    case R_X86_64_REX_GOTPCRELX:
-    case R_X86_64_CODE_4_GOTPCRELX:
-      expr = R_GOT_PC;
-      break;
-
-      // PLT-generating relocation:
-    case R_X86_64_PLT32:
-      rs.processR_PLT_PC(type, offset, addend, sym);
-      continue;
-
-      // TLS relocations:
-    case R_X86_64_TPOFF32:
-    case R_X86_64_TPOFF64:
-      if (rs.checkTlsLe(offset, sym, type))
-        continue;
-      expr = R_TPREL;
-      break;
-    case R_X86_64_GOTTPOFF:
-    case R_X86_64_CODE_4_GOTTPOFF:
-    case R_X86_64_CODE_6_GOTTPOFF:
-      rs.handleTlsIe(R_GOT_PC, type, offset, addend, sym);
-      continue;
-    case R_X86_64_TLSGD:
-      if (rs.handleTlsGd(R_TLSGD_PC, R_GOT_PC, R_TPREL, type, offset, addend,
-                         sym))
-        ++it;
-      continue;
-    case R_X86_64_TLSLD:
-      if (rs.handleTlsLd(R_TLSLD_PC, type, offset, addend, sym))
-        ++it;
-      continue;
-    case R_X86_64_DTPOFF32:
-    case R_X86_64_DTPOFF64:
-      sec.addReloc(
-          {ctx.arg.shared ? R_DTPREL : R_TPREL, type, offset, addend, &sym});
-      continue;
-    case R_X86_64_TLSDESC_CALL:
-      // For executables, TLSDESC is optimized to IE or LE. Use R_TPREL as the
-      // rewrites for this relocation are identical.
-      if (!ctx.arg.shared)
-        sec.addReloc({R_TPREL, type, offset, addend, &sym});
-      continue;
-    case R_X86_64_GOTPC32_TLSDESC:
-    case R_X86_64_CODE_4_GOTPC32_TLSDESC:
-      rs.handleTlsDesc(R_TLSDESC_PC, R_GOT_PC, type, offset, addend, sym);
-      continue;
-
-      // Misc relocations:
-    case R_X86_64_SIZE32:
-    case R_X86_64_SIZE64:
-      expr = R_SIZE;
-      break;
-
-    default:
-      Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset)
-               << "unknown relocation (" << type.v << ") against symbol "
-               << &sym;
-      continue;
-    }
-    rs.process(expr, type, offset, sym, addend);
-  }
-
-  if (ctx.arg.branchToBranch)
-    llvm::stable_sort(sec.relocs(),
-                      [](auto &l, auto &r) { return l.offset < r.offset; });
-}
-
-void X86_64::scanSection(InputSectionBase &sec) {
-  if (ctx.arg.is64)
-    elf::scanSection1<X86_64, ELF64LE>(*this, sec);
-  else // ilp32
-    elf::scanSection1<X86_64, ELF32LE>(*this, sec);
-}
-
 void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
                             uint64_t val) const {
   if (rel.type == R_X86_64_TLSGD) {
@@ -663,6 +558,11 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
     }
     loc[-2] = 0x8b;
     write32le(loc, val);
+  } else {
+    // Convert call *x at tlsdesc(%rax) to xchg ax, ax.
+    assert(rel.type == R_X86_64_TLSDESC_CALL);
+    loc[0] = 0x66;
+    loc[1] = 0x90;
   }
 }
 
@@ -1015,9 +915,9 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_X86_64_CODE_4_GOTPC32_TLSDESC:
   case R_X86_64_TLSDESC_CALL:
   case R_X86_64_TLSGD:
-    if (rel.expr == R_TPREL) {
+    if (rel.expr == R_RELAX_TLS_GD_TO_LE) {
       relaxTlsGdToLe(loc, rel, val);
-    } else if (rel.expr == R_GOT_PC) {
+    } else if (rel.expr == R_RELAX_TLS_GD_TO_IE) {
       relaxTlsGdToIe(loc, rel, val);
     } else {
       checkInt(ctx, loc, val, 32, rel);
@@ -1025,7 +925,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     }
     break;
   case R_X86_64_TLSLD:
-    if (rel.expr == R_TPREL) {
+    if (rel.expr == R_RELAX_TLS_LD_TO_LE) {
       relaxTlsLdToLe(loc, rel, val);
     } else {
       checkInt(ctx, loc, val, 32, rel);
@@ -1035,7 +935,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_X86_64_GOTTPOFF:
   case R_X86_64_CODE_4_GOTTPOFF:
   case R_X86_64_CODE_6_GOTTPOFF:
-    if (rel.expr == R_TPREL) {
+    if (rel.expr == R_RELAX_TLS_IE_TO_LE) {
       relaxTlsIeToLe(loc, rel, val);
     } else {
       checkInt(ctx, loc, val, 32, rel);

diff  --git a/lld/ELF/RelocScan.h b/lld/ELF/RelocScan.h
index d52afda26effb..01750431b7468 100644
--- a/lld/ELF/RelocScan.h
+++ b/lld/ELF/RelocScan.h
@@ -66,112 +66,8 @@ class RelocScan {
                                 uint64_t relOff) const;
   void process(RelExpr expr, RelType type, uint64_t offset, Symbol &sym,
                int64_t addend) const;
-  // Process relocation after needsGot/needsPlt flags are already handled.
-  void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym,
-                  int64_t addend) const;
   unsigned handleTlsRelocation(RelExpr expr, RelType type, uint64_t offset,
                                Symbol &sym, int64_t addend);
-
-  // Process R_PC relocations. These are the most common relocation type, so we
-  // inline the isStaticLinkTimeConstant check.
-  void processR_PC(RelType type, uint64_t offset, int64_t addend, Symbol &sym) {
-    if (LLVM_UNLIKELY(sym.isGnuIFunc()))
-      sym.setFlags(HAS_DIRECT_RELOC);
-    if (sym.isPreemptible || (isAbsolute(sym) && ctx.arg.isPic))
-      processAux(R_PC, type, offset, sym, addend);
-    else
-      sec->addReloc({R_PC, type, offset, addend, &sym});
-  }
-
-  // Process R_PLT_PC relocations. These are very common (calls), so we inline
-  // the isStaticLinkTimeConstant check. Non-preemptible symbols are optimized
-  // to R_PC (direct call).
-  void processR_PLT_PC(RelType type, uint64_t offset, int64_t addend,
-                       Symbol &sym) {
-    if (LLVM_UNLIKELY(sym.isGnuIFunc())) {
-      process(R_PLT_PC, type, offset, sym, addend);
-      return;
-    }
-    if (sym.isPreemptible) {
-      sym.setFlags(NEEDS_PLT);
-      sec->addReloc({R_PLT_PC, type, offset, addend, &sym});
-    } else if (!(isAbsolute(sym) && ctx.arg.isPic)) {
-      sec->addReloc({R_PC, type, offset, addend, &sym});
-    } else {
-      processAux(R_PC, type, offset, sym, addend);
-    }
-  }
-
-  // Handle TLS Initial-Exec relocation.
-  void handleTlsIe(RelExpr ieExpr, RelType type, uint64_t offset,
-                   int64_t addend, Symbol &sym) {
-    if (!ctx.arg.shared && !sym.isPreemptible) {
-      // Optimize to Local Exec.
-      sec->addReloc({R_TPREL, type, offset, addend, &sym});
-    } else {
-      ctx.hasTlsIe.store(true, std::memory_order_relaxed);
-      sym.setFlags(NEEDS_TLSIE);
-      // R_GOT (absolute GOT address) needs a RELATIVE dynamic relocation in
-      // PIC. This is used by R_386_TLS_IE.
-      if (ieExpr == R_GOT && ctx.arg.isPic)
-        sec->getPartition(ctx).relaDyn->addRelativeReloc(
-            ctx.target->relativeRel, *sec, offset, sym, addend, type, ieExpr);
-      else
-        sec->addReloc({ieExpr, type, offset, addend, &sym});
-    }
-  }
-
-  // Handle TLS Local-Dynamic relocation. Returns true if the __tls_get_addr
-  // call should be skipped (i.e., caller should ++it).
-  bool handleTlsLd(RelExpr sharedExpr, RelType type, uint64_t offset,
-                   int64_t addend, Symbol &sym) {
-    if (ctx.arg.shared) {
-      ctx.needsTlsLd.store(true, std::memory_order_relaxed);
-      sec->addReloc({sharedExpr, type, offset, addend, &sym});
-      return false;
-    }
-    // Optimize to Local Exec.
-    sec->addReloc({R_TPREL, type, offset, addend, &sym});
-    return true;
-  }
-
-  // Handle TLS General-Dynamic relocation. Returns true if the __tls_get_addr
-  // call should be skipped (i.e., caller should ++it).
-  bool handleTlsGd(RelExpr sharedExpr, RelExpr ieExpr, RelExpr leExpr,
-                   RelType type, uint64_t offset, int64_t addend, Symbol &sym) {
-    if (ctx.arg.shared) {
-      sym.setFlags(NEEDS_TLSGD);
-      sec->addReloc({sharedExpr, type, offset, addend, &sym});
-      return false;
-    }
-    if (sym.isPreemptible) {
-      // Optimize to Initial Exec.
-      ctx.hasTlsIe.store(true, std::memory_order_relaxed);
-      sym.setFlags(NEEDS_TLSIE);
-      sec->addReloc({ieExpr, type, offset, addend, &sym});
-    } else {
-      // Optimize to Local Exec.
-      sec->addReloc({leExpr, type, offset, addend, &sym});
-    }
-    return true;
-  }
-
-  // Handle TLSDESC relocation.
-  void handleTlsDesc(RelExpr sharedExpr, RelExpr ieExpr, RelType type,
-                     uint64_t offset, int64_t addend, Symbol &sym) {
-    if (ctx.arg.shared) {
-      sym.setFlags(NEEDS_TLSDESC);
-      sec->addReloc({sharedExpr, type, offset, addend, &sym});
-    } else if (sym.isPreemptible) {
-      // Optimize to Initial Exec.
-      ctx.hasTlsIe.store(true, std::memory_order_relaxed);
-      sym.setFlags(NEEDS_TLSIE);
-      sec->addReloc({ieExpr, type, offset, addend, &sym});
-    } else {
-      // Optimize to Local Exec.
-      sec->addReloc({R_TPREL, type, offset, addend, &sym});
-    }
-  }
 };
 
 template <class ELFT, class RelTy>
@@ -203,7 +99,8 @@ void RelocScan::scan(typename Relocs<RelTy>::const_iterator &it, RelType type,
 
   // Ensure GOT or GOTPLT is created for relocations that reference their base
   // addresses without directly creating entries.
-  if (oneof<R_GOTPLTREL, R_GOTPLT, R_TLSGD_GOTPLT>(expr)) {
+  if (oneof<R_GOTPLTONLY_PC, R_GOTPLTREL, R_GOTPLT, R_PLT_GOTPLT,
+            R_TLSDESC_GOTPLT, R_TLSGD_GOTPLT>(expr)) {
     ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
   } else if (oneof<R_GOTONLY_PC, R_GOTREL, RE_PPC32_PLTREL>(expr)) {
     ctx.in.got->hasGotOffRel.store(true, std::memory_order_relaxed);

diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 797acb08b0506..16c2e50364e29 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -983,16 +983,6 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
     sym.setFlags(HAS_DIRECT_RELOC);
   }
 
-  processAux(expr, type, offset, sym, addend);
-}
-
-// Process relocation after needsGot/needsPlt flags are already handled.
-// This is the bottom half of process(), handling isStaticLinkTimeConstant
-// check, dynamic relocations, copy relocations, and error reporting.
-void RelocScan::processAux(RelExpr expr, RelType type, uint64_t offset,
-                           Symbol &sym, int64_t addend) const {
-  const bool isIfunc = sym.isGnuIFunc();
-
   // If the relocation is known to be a link-time constant, we know no dynamic
   // relocation will be created, pass the control to relocateAlloc() or
   // relocateNonAlloc() to resolve it.
@@ -1314,7 +1304,7 @@ unsigned RelocScan::handleTlsRelocation(RelExpr expr, RelType type,
       sec->addReloc({R_RELAX_TLS_IE_TO_LE, type, offset, addend, &sym});
     } else if (expr != R_TLSIE_HINT) {
       sym.setFlags(NEEDS_TLSIE);
-      // R_GOT needs a relative relocation for PIC on Hexagon.
+      // R_GOT needs a relative relocation for PIC on i386 and Hexagon.
       if (expr == R_GOT && ctx.arg.isPic &&
           !ctx.target->usesOnlyLowPageBits(type))
         addRelativeReloc<true>(ctx, *sec, offset, sym, addend, expr, type);


        


More information about the llvm-commits mailing list