From eea7d32bd262bb5f61790c42ebaa147aa26c3979 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 12 Mar 2025 19:49:52 -0700 Subject: [PATCH] [MC] Move fixSymbolsInTLSFixups to ELFObjectWriter so that we only need to do it once during recordRelocation. In the future, we should change fixSymbolsInTLSFixups to apply to MCValue instead of MCExpr, similar to GNU assembler. --- llvm/include/llvm/MC/MCELFObjectWriter.h | 2 + llvm/include/llvm/MC/MCELFStreamer.h | 2 - llvm/lib/MC/ELFObjectWriter.cpp | 89 +++++++++++++++++++++ llvm/lib/MC/MCELFStreamer.cpp | 99 +----------------------- 4 files changed, 92 insertions(+), 100 deletions(-) diff --git a/llvm/include/llvm/MC/MCELFObjectWriter.h b/llvm/include/llvm/MC/MCELFObjectWriter.h index 3b7a0c8a7025..a61abd58e835 100644 --- a/llvm/include/llvm/MC/MCELFObjectWriter.h +++ b/llvm/include/llvm/MC/MCELFObjectWriter.h @@ -189,6 +189,8 @@ public: bool checkRelocation(MCContext &Ctx, SMLoc Loc, const MCSectionELF *From, const MCSectionELF *To); + void fixSymbolsInTLSFixups(MCAssembler &Asm, const MCExpr *Expr); + unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; } void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; } diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h index 8065d17546d2..aa703a06979c 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -159,10 +159,8 @@ public: private: bool isBundleLocked() const; - void emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; - void fixSymbolsInTLSFixups(const MCExpr *expr); void finalizeCGProfileEntry(const MCSymbolRefExpr *&S, uint64_t Offset); void finalizeCGProfile(); diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 68e7f1785fa2..d0e56162f616 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1468,6 +1468,9 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, return; } + if (Fixup.getValue()) + fixSymbolsInTLSFixups(Asm, Fixup.getValue()); + const MCSymbolELF *RenamedSymA = SymA; if (SymA) { if (const MCSymbolELF *R = Renames.lookup(SymA)) @@ -1502,6 +1505,92 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( return &SymA.getSection() == FB.getParent(); } +void ELFObjectWriter::fixSymbolsInTLSFixups(MCAssembler &Asm, + const MCExpr *expr) { + switch (expr->getKind()) { + case MCExpr::Target: + cast(expr)->fixELFSymbolsInTLSFixups(Asm); + break; + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *be = cast(expr); + fixSymbolsInTLSFixups(Asm, be->getLHS()); + fixSymbolsInTLSFixups(Asm, be->getRHS()); + break; + } + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &symRef = *cast(expr); + switch (symRef.getKind()) { + default: + return; + case MCSymbolRefExpr::VK_GOTTPOFF: + case MCSymbolRefExpr::VK_INDNTPOFF: + case MCSymbolRefExpr::VK_NTPOFF: + case MCSymbolRefExpr::VK_GOTNTPOFF: + case MCSymbolRefExpr::VK_TLSCALL: + case MCSymbolRefExpr::VK_TLSDESC: + case MCSymbolRefExpr::VK_TLSGD: + case MCSymbolRefExpr::VK_TLSLD: + case MCSymbolRefExpr::VK_TLSLDM: + case MCSymbolRefExpr::VK_TPOFF: + case MCSymbolRefExpr::VK_TPREL: + case MCSymbolRefExpr::VK_DTPOFF: + case MCSymbolRefExpr::VK_DTPREL: + case MCSymbolRefExpr::VK_PPC_DTPMOD: + case MCSymbolRefExpr::VK_PPC_TPREL_LO: + case MCSymbolRefExpr::VK_PPC_TPREL_HI: + case MCSymbolRefExpr::VK_PPC_TPREL_HA: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGH: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: + case MCSymbolRefExpr::VK_PPC_DTPREL_LO: + case MCSymbolRefExpr::VK_PPC_DTPREL_HI: + case MCSymbolRefExpr::VK_PPC_DTPREL_HA: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: + case MCSymbolRefExpr::VK_PPC_TLS: + case MCSymbolRefExpr::VK_PPC_TLS_PCREL: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: + break; + } + Asm.registerSymbol(symRef.getSymbol()); + cast(symRef.getSymbol()).setType(ELF::STT_TLS); + break; + } + + case MCExpr::Unary: + fixSymbolsInTLSFixups(Asm, cast(expr)->getSubExpr()); + break; + } +} + uint64_t ELFObjectWriter::writeObject(MCAssembler &Asm) { uint64_t Size = ELFWriter(*this, OS, IsLittleEndian, diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index df559f1f6a16..2668bc1b2920 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -318,7 +318,6 @@ void MCELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { if (isBundleLocked()) report_fatal_error("Emitting values inside a locked bundle is forbidden"); - fixSymbolsInTLSFixups(Value); MCObjectStreamer::emitValueImpl(Value, Size, Loc); } @@ -351,91 +350,6 @@ void MCELFStreamer::emitIdent(StringRef IdentString) { popSection(); } -void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { - switch (expr->getKind()) { - case MCExpr::Target: - cast(expr)->fixELFSymbolsInTLSFixups(getAssembler()); - break; - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *be = cast(expr); - fixSymbolsInTLSFixups(be->getLHS()); - fixSymbolsInTLSFixups(be->getRHS()); - break; - } - - case MCExpr::SymbolRef: { - const MCSymbolRefExpr &symRef = *cast(expr); - switch (symRef.getKind()) { - default: - return; - case MCSymbolRefExpr::VK_GOTTPOFF: - case MCSymbolRefExpr::VK_INDNTPOFF: - case MCSymbolRefExpr::VK_NTPOFF: - case MCSymbolRefExpr::VK_GOTNTPOFF: - case MCSymbolRefExpr::VK_TLSCALL: - case MCSymbolRefExpr::VK_TLSDESC: - case MCSymbolRefExpr::VK_TLSGD: - case MCSymbolRefExpr::VK_TLSLD: - case MCSymbolRefExpr::VK_TLSLDM: - case MCSymbolRefExpr::VK_TPOFF: - case MCSymbolRefExpr::VK_TPREL: - case MCSymbolRefExpr::VK_DTPOFF: - case MCSymbolRefExpr::VK_DTPREL: - case MCSymbolRefExpr::VK_PPC_DTPMOD: - case MCSymbolRefExpr::VK_PPC_TPREL_LO: - case MCSymbolRefExpr::VK_PPC_TPREL_HI: - case MCSymbolRefExpr::VK_PPC_TPREL_HA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGH: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: - case MCSymbolRefExpr::VK_PPC_DTPREL_LO: - case MCSymbolRefExpr::VK_PPC_DTPREL_HI: - case MCSymbolRefExpr::VK_PPC_DTPREL_HA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: - case MCSymbolRefExpr::VK_PPC_TLS: - case MCSymbolRefExpr::VK_PPC_TLS_PCREL: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: - break; - } - getAssembler().registerSymbol(symRef.getSymbol()); - cast(symRef.getSymbol()).setType(ELF::STT_TLS); - break; - } - - case MCExpr::Unary: - fixSymbolsInTLSFixups(cast(expr)->getSubExpr()); - break; - } -} - void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE, uint64_t Offset) { const MCSymbol *S = &SRE->getSymbol(); @@ -478,15 +392,6 @@ void MCELFStreamer::finalizeCGProfile() { popSection(); } -void MCELFStreamer::emitInstToFragment(const MCInst &Inst, - const MCSubtargetInfo &STI) { - this->MCObjectStreamer::emitInstToFragment(Inst, STI); - MCRelaxableFragment &F = *cast(getCurrentFragment()); - - for (auto &Fixup : F.getFixups()) - fixSymbolsInTLSFixups(Fixup.getValue()); -} - // A fragment can only have one Subtarget, and when bundling is enabled we // sometimes need to use the same fragment. We give an error if there // are conflicting Subtargets. @@ -548,10 +453,8 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst, DF->getFixups(), STI); auto Fixups = MutableArrayRef(DF->getFixups()).slice(FixupStartIndex); - for (auto &Fixup : Fixups) { + for (auto &Fixup : Fixups) Fixup.setOffset(Fixup.getOffset() + CodeOffset); - fixSymbolsInTLSFixups(Fixup.getValue()); - } DF->setHasInstructions(STI); if (!Fixups.empty() && Fixups.back().getTargetKind() ==